问题描述
转载]转:关于java文件读写、字节流、字符流的一点新得一.转载网址:http://my.oschina.net/u/232879/blog/155440关于编码方式我们不讲,有兴趣自己去看,这里大概提一下。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,Charseta)带编码方式的构造函数,在知道要读入的文本的编码方式的情况下。)2、使用Reader类的子类读取的单位为字符,即中文、英文都为两个字节大小,故而都不受影响。如果将读取到的每一个字符保存到一个字符数组char[]a中问题又来了:(特别注意!!!)如对字符数组char[]使用toString()函数时同样会遇到错误的分隔,建议使用String类的构造函数String(char[]c)来构造正确的字符划分。当然有更简便的方法:如果你采用的读取函数是readline()当然不存在如上字符转换的问题(请注意在InputStream类系的子类中是不存在类似readline()这样的函数的,只有read()这样的函数)。StringBuffer就像一个动态数组一样,我可以保存任意长的char字符,需要时只需将他们读取出来就行了。在这里我们将读到的每一个byte转化为一个char保存在StringBuffer中,需要时将他们读出再转化为byte,此过程数据不会溢出,精度不会受到损失。另外好像对转义字符’’,String类的split(Stringa)函数出现了问题,这是怎么回事?java本身的bug吗?当一个带完整文件夹路径的文件名,传给File类的mkdir(StringFilePathAndName)函数时一定要小心,如果该文件名中包含的文件路径不存在(或者说还未被创建的)的话,直接用此函数创建文件是会出错的,你需要先一层层的创建好这些路径方可创建该路径下的文件。(创建路径和文件其实是一个函数,本质上也没有什么区别!^_^)下面是我写的测试程序,代码如下。importjava.io.BufferedInputStream;importjava.io.BufferedOutputStream;importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.File;importjava.io.FileInputStream;importjava.io.FileNotFoundException;importjava.io.FileOutputStream;importjava.io.FileReader;importjava.io.FileWriter;importjava.io.IOException;importjava.io.UnsupportedEncodingException;importjava.nio.CharBuffer;publicclassFileReaderWriter{publicFileReaderWriter(){}publicStringreader(Stringfullpath)throwsFileNotFoundException//用readline的方式读取文件内容{try{Stringcontent="";Filefile=newFile(fullpath);if(file.exists()){System.out.println("FILE:"+fullpath+"EXIST,NowIwillreadit!");FileReaderfr=newFileReader(file);BufferedReaderbr=newBufferedReader(fr);try{System.out.println("-----------Nowiscontentoffile(Reading):----------");intn=0;for(;;){n++;Stringtemp=br.readLine();System.out.println("Line"+n+":");System.out.println(temp);content+=temp;if(temp==null){System.out.println("----------OVER---------");br.close();break;}}}catch(IOExceptionex){ex.printStackTrace();}}else{System.out.println("FILE:"+fullpath+"isNotEXIST"+"nowIwilldonothingbutexit");}returncontent;}catch(FileNotFoundExceptionex){ex.printStackTrace();}returnnull;}publicvoidwriter(Stringfullpath,Stringcontent){Filef=newFile(fullpath);if(!f.exists()){System.out.println("Fileisnotexist!NowIwillcreateit!");createfile(fullpath);//f.mkdir();//带有目录时这样创建是不行的}FileWriterfw;try{fw=newFileWriter(f);BufferedWriterbw=newBufferedWriter(fw);System.out.println("IamWritingNow!");bw.write(content);bw.close();System.out.println("-----------WritingContent:---------");System.out.println(content);System.out.println("------------WritingComplete!-------------");}catch(IOExceptionex){ex.printStackTrace();}}publicstaticvoidmain(String[]args){FileReaderWriterfrw=newFileReaderWriter();//做一下各种文件路径的测试^_^//Stringpath="info.txt";//Stringpath2="stream.txt";//Stringpath="d:try1/12info.txt";//Stringpath2="d:try21/2/3stream.txt";//Stringpath2="4/2/3stream.txt";Stringpath="12info.txt";Stringpath2="1/2/stream.txt";Stringtest="";Stringtext1="Hello,MynameisGuiZhiPengn";Stringtext2="我的名字是桂志鹏n";Stringtext3="IcomeFromChina!NowI'mStudyinginWuHanUniversityofHuBeiProvince.n";Stringtext4="我来自中国,现在湖北省的武汉大学读书";test=text1+text2+text3+text4;frw.writer(path,test);try{frw.reader(path);}catch(FileNotFoundExceptionex){ex.printStackTrace();}frw.outputstream(path2,test);frw.inputstream(path2);//frw.inputstream("LoginEndpoint.wsdl");}publicStringreaderbycharacter(Stringfullpath)throwsIOException//试图通过一个字节一个字节(或者一个字符一个字符)的读取方式读出流后恢复字符编码,{Stringcontent="";Filef=newFile(fullpath);FileReaderfr;intin;try{fr=newFileReader(f);BufferedReaderbr=newBufferedReader(fr);StringBuffersb=newStringBuffer();//byte[]save=newbyte[1000];//char[]save=newchar[1000];intnum=0;do{in=br.read();if(in!=-1){byteb=(byte)in;//强制转化会出现问题(有中文时,将char转化为byte损失位数,将使中文显示有问题)charc=(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("CHARNum:"+sb.length());//content=newString(save);content=sb.toString();//content=newString(t);//content=t.toString();System.out.println(content);writer("test.txt",content);}catch(FileNotFoundExceptionex){ex.printStackTrace();}returncontent;}publicStringinputstream(Stringfullpath){Filef=newFile(fullpath);intinbyte=0;Stringcontent="";StringBuffersb=newStringBuffer();intnum=0;try{FileInputStreamfin=newFileInputStream(f);BufferedInputStreambin=newBufferedInputStream(fin);do{try{inbyte=bin.read();}catch(IOExceptionex){ex.printStackTrace();}if(inbyte!=-1){sb.append((char)inbyte);//System.out.println((char)inbyte);num++;}}while(inbyte!=-1);try{bin.close();}catch(IOExceptionex){ex.printStackTrace();}System.out.println("Num:"+num);byte[]save=newbyte[num];for(inti=0;i{save[i]=(byte)sb.charAt(i);}content=newString(save);System.out.println(content);System.out.println("Readingstreamsuccess!");}catch(FileNotFoundExceptionex){ex.printStackTrace();}returncontent;}publicvoidoutputstream(Stringfullpath,Stringcontent){Filef=newFile(fullpath);if(!f.exists()){System.out.println("Fileisnotexist!NowIwillcreateit!");createfile(fullpath);//f.mkdir();//fullpath中带有目录时这样创建方式是不行的}intinbyte=0;try{FileOutputStreamfout=newFileOutputStream(f);BufferedOutputStreambout=newBufferedOutputStream(fout);try{bout.write(content.getBytes());}catch(IOExceptionex){ex.printStackTrace();}try{bout.close();}catch(IOExceptionex){ex.printStackTrace();}System.out.println("WritingStreamSuccess!");}catch(FileNotFoundExceptionex){ex.printStackTrace();}}publicvoidcreatefile(Stringfullpath){System.out.println("---------InCreateFileFouction---------");String[]paths=null;Stringpropath=null;Filef;inti;if(fullpath.indexOf("")!=-1){System.out.println("?????");//paths=fullpath.split("");此函数执行有问题:java.util.regex.PatternSyntaxException:Unexpectedinternalerrornearindex1fullpath=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];elsepropath=paths[0];f=newFile(propath);if(!f.exists())f.mkdir();}}else{f=newFile(fullpath);}}}后记:一位朋友对我的文章给出了很好的答案^_^顶了,谢谢当操作的对象不需要关心编码问题时应该使用InputStream/OutputStream系列的类。例如读取二进制文件(EXE等)。当需要关心编码问题时应该使用Reader/Writer系列的类。String.split()的参数是正则表达式。所以想以分割字符串的话应该这样:str.("");二.简单的代码分析PrintWriterclassMySendCommondThreadextendsThread{privateStringcommond;publicMySendCommondThread(Stringcommond){this.commond=commond;}publicvoidrun(){//实例化Sockettry{Socketsocket=newSocket(serverUrl,serverPort);PrintWriterout=newPrintWriter(socket.getOutputStream());out.println(commond);out.flush();}catch(UnknownHostExceptione){}catch(IOExceptione){}}}1.android手册publicPrintWriter(OutputStreamout)ConstructsanewPrintWriterwithoutasitstargetstream.Bydefault,thenewprintwriterdoesnotautomaticallyflushitscontentstothetargetstreamwhenanewlineisencountered.Parametersoutthetargetoutputstream2.分析这里使用的是PrintWriter的out构造函数,这个构造函数的唯一参数是OutputStream,在这个实例中是sockt.getOutPutStream(),即将字符流写入到socket的输出流中。然后在PrintWriter实例化对象out中,调用了println(Stringstr)方法即out.println(commond),也就是实现将commond换行显示出来。在使用out的构造函数中,由于不能像publicPrintWriter(OutputStreamout,booleanautoFlush)一样将缓冲区的数据挤出,因此需要用到out.flush()方法将缓冲区的数据手动挤出。