[转载]转:关于java文件读写、字节流、字符流的一点新得
关于编码方式我们不讲,有兴趣自己去看,这里大概提一下。
UTF-16采用等幅编码,即每个字符占2个字节。优点:简单;缺点:西文会膨胀到200%,冗余!而且字与字之间的疆界不好找,容易划分错误,没有考虑好前缀问题。这一点huffman编码做的很好。
UTF-8为不等幅编码,有1到3个字节的不等长度。优点:由于采用了很好的前缀,不会出现字之间疆界不好找和划分错误的情况。缺点:中日韩等文字膨胀到150%,冗余。现在主要说一下字节流、字符流的区别,顾名思义字节流是以字节为单位读取数据的,而字符流是以字符为单位读取的。我们都知道java采用了两种I/O读写 方式主要有两个超类系:一个是inputstream和outputstream字节流类系;另一个是Reader和Writer字符流类系。使用他们来 读写文本文件时有些要注意的问题:
1、使用inputstream类的子类读取的单位为字节,对于英语字母(只占一个字节)不受任何影响,而中文文字在unicode编码为两个字节(或者以上?),在读取中一个中文文字会被划分为两个(或多个)字节,因而受到影响。
如果将读取到的字节保存在byte[]数组中,为了正确地处理字节到字符的转化应注意如下问题: 对byte[]数组采用toString的方法转化为字符,会导致错误的分割方式生成字符,不能正确地显示字符;而采用String的构造函数String(byte[] b)可以正确的分割构造字符。(或者String(byte[] b, Charset a)带编码方式的构造函数,在知道要读入的文本的编码方式的情况下。) 2、使用Reader类的子类读取的单位为字符,即中文、英文都为两个字节大小,故而都不受影响。 如果将读取到的每一个字符保存到一个字符数组char[] a中问题又来了: (特别注意!!!)如对字符数组char[]使用toString()函数时同样会遇到错误的分隔,建议使用String类的构造函数String(char[] c)来构造正确的字符划分。 当然有更简便的方法:如果你采用的读取函数是readline()当然不存在如上字符转换的问题(请注意在InputStream类系的子类中是不存在类似readline()这样的函数的,只有read()这样的函数)。StringBuffer就像一个动态数组一样,我可以保存任意长的char字符,需要时只需将他们读取出来就行了。
在这里我们将读到的每一个byte转化为一个char保存在StringBuffer中,需要时将他们读出再转化为byte,此过程数据不会溢出,精度不会受到损失。另外好像对转义字符 ’\’,String类的split(String a)函数出现了问题,这是怎么回事?java本身的bug吗?
当一个带完整文件夹路径的文件名,传给File类的mkdir(String FilePathAndName)函数时一定要小心,如果该文件名中包含的文件路径不存在(或者说还未被创建的)的话,直接用此函数创建文件是会出错的, 你需要先一层层的创建好这些路径方可创建该路径下的文件。(创建路径和文件其实是一个函数,本质上也没有什么区别!^_^)
下面是我写的测试程序,代码如下。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.nio.CharBuffer;public class FileReaderWriter {
public FileReaderWriter() { } public String reader(String fullpath) throws FileNotFoundException //用readline的方式读取文件内容 { try { String content =""; File file = new File(fullpath);
if(file.exists())
{ System.out.println("FILE: "+fullpath+" EXIST, Now I will read it!"); FileReader fr = new FileReader(file); BufferedReader br = new BufferedReader(fr); try { System.out.println("-----------Now is content of file(Reading):----------"); int n = 0; for(;;) { n++; String temp = br.readLine(); System.out.println("Line"+n+":"); System.out.println(temp); content+=temp; if(temp==null) { System.out.println("----------OVER---------"); br.close(); break; } } } catch (IOException ex) { ex.printStackTrace(); }}
else { System.out.println("FILE:"+fullpath+" is Not EXIST"+"now I will do nothing but exit"); } return content; } catch (FileNotFoundException ex) { ex.printStackTrace(); } return null; }public void writer(String fullpath,String content)
{ File f = new File(fullpath); if(!f.exists()) { System.out.println("File is not exist! Now I will create it!"); createfile(fullpath); //f.mkdir();//带有目录时这样创建是不行的 } FileWriter fw; try { fw = new FileWriter(f); BufferedWriter bw = new BufferedWriter(fw); System.out.println("I am Writing Now!"); bw.write(content); bw.close(); System.out.println("-----------Writing Content:---------"); System.out.println(content); System.out.println("------------Writing Complete!-------------"); } catch (IOException ex) { ex.printStackTrace(); } } public static void main(String[] args) { FileReaderWriter frw = new FileReaderWriter(); //做一下各种文件路径的测试^_^ //String path ="info.txt"; //String path2 = "stream.txt"; //String path ="d:\try1/1\2\info.txt"; //String path2 = "d:\try2\1/2/3\stream.txt"; //String path2 = "\4/2/3\stream.txt";String path ="1\2\info.txt";
String path2 = "1/2/stream.txt"; String test =""; String text1 ="Hello, My name is GuiZhiPengn"; String text2 ="我的名字是桂志鹏n"; String text3 ="I come From China! Now I'm Studying in WuHan University of HuBei Province.n"; String text4 ="我来自中国,现在湖北省的武汉大学读书"; test= text1+text2+text3+text4; frw.writer(path,test); try { frw.reader(path); } catch (FileNotFoundException ex) { ex.printStackTrace(); }frw.outputstream(path2,test);
frw.inputstream(path2); //frw.inputstream("LoginEndpoint.wsdl"); }public String readerbycharacter(String fullpath) throws IOException
//试图通过一个字节一个字节(或者一个字符一个字符)的读取方式读出流后恢复字符编码, { String content =""; File f = new File(fullpath); FileReader fr; int in; try { fr = new FileReader(f); BufferedReader br = new BufferedReader(fr); StringBuffer sb = new StringBuffer(); //byte[] save = new byte[1000]; //char[] save = new char[1000]; int num =0; do { in = br.read(); if(in!=-1) { byte b = (byte)in;//强制转化会出现问题(有中文时,将char转化为byte损失位数,将使中文显示有问题) char c = (char)in; sb.append(c); System.out.println(c); System.out.println(b); System.out.println((char)b); //save[num++] = b; num++; } }while(in!=-1); br.close(); System.out.println("NUM: "+num); System.out.println("CHAR Num: " + sb.length()); //content = new String(save); content = sb.toString(); //content = new String(t); //content = t.toString(); System.out.println(content); writer("test.txt",content); } catch (FileNotFoundException ex) { ex.printStackTrace(); } return content; }public String inputstream(String fullpath)
{File f = new File(fullpath);
int inbyte = 0; String content =""; StringBuffer sb = new StringBuffer(); int num=0; try { FileInputStream fin = new FileInputStream(f); BufferedInputStream bin = new BufferedInputStream(fin); do { try { inbyte = bin.read(); } catch (IOException ex) { ex.printStackTrace(); } if(inbyte!=-1) { sb.append((char)inbyte); //System.out.println((char)inbyte); num++; } }while(inbyte!=-1); try { bin.close(); } catch (IOException ex) { ex.printStackTrace(); } System.out.println("Num: "+num); byte[] save = new byte[num]; for(int i = 0; i { save[i] = (byte)sb.charAt(i); } content = new String(save); System.out.println(content); System.out.println("Reading stream success!");} catch (FileNotFoundException ex) {
ex.printStackTrace(); } return content; }public void outputstream(String fullpath, String content)
{ File f = new File(fullpath); if(!f.exists()) { System.out.println("File is not exist! Now I will create it!"); createfile(fullpath); //f.mkdir();//fullpath中带有目录时这样创建方式是不行的 } int inbyte = 0; try { FileOutputStream fout = new FileOutputStream(f); BufferedOutputStream bout = new BufferedOutputStream(fout); try { bout.write(content.getBytes()); } catch (IOException ex) { ex.printStackTrace(); } try { bout.close(); } catch (IOException ex) { ex.printStackTrace(); } System.out.println("Writing Stream Success!");} catch (FileNotFoundException ex) {
ex.printStackTrace(); }}
public void createfile(String fullpath)
{ System.out.println("---------In CreateFile Fouction---------"); String[] paths = null; String propath = null; File f; int i; if(fullpath.indexOf("")!=-1) { System.out.println("?????"); //paths = fullpath.split("");此函数执行有问题:java.util.regex.PatternSyntaxException: Unexpected internal error near index 1 fullpath = fullpath.replace('\','/'); } if(fullpath.indexOf("/")!=-1) { System.out.println("!!!!!"); paths = fullpath.split("/"); } //if(paths[0].indexOf(":")!=-1) if(paths!=null) { for(i = 0; i { if(propath!=null) propath=propath+"/"+paths[i]; else propath = paths[0]; f = new File(propath); if(!f.exists()) f.mkdir(); } } else { f = new File(fullpath); } } }后记:一位朋友对我的文章给出了很好的答案^_^顶了,谢谢
当操作的对象不需要关心编码问题时应该使用InputStream/OutputStream系列的类。例如读取二进制文件(EXE等)。
当需要关心编码问题时应该使用Reader/Writer系列的类。
String.split()的参数是正则表达式。所以想以分割字符串的话应该这样:str.("\");