------- android培训、java培训、期待与您交流! ----------
一、概述
文件通常是由一连串的字节或字符构成,组成文件的字节序列称为字节流;组成文件的字符序列称为字符流。Java 中根据流的方向可以分为输入流和输出流。输入流是将文件或其它输入设备的数据加载到内存的过程;输出流恰恰相反,是将内存中的数据保存到文件或其他输出设备。
IO流泛指对某个设备或环境进行数据的数据或输出。
数据的最常见体现形式是:文件。
InputStream 和OutputStream(字节流
)
Reader 和Writer(字符流)
二、文件流
1、FileWriter(文件字符输入流)
创建文件
package com.File;
import java.io.*;
public class FileWriterDemo {
public static void main(String[] args){//创建一个FileWriter对象。该对象一被初始化就必须要明确被操作的文件。FileWriter fw = null ;try {//而且该文件会被创建到指定目录下。如果该目录下已有同名文件,将被覆盖。//其实该步就是在明确数据要存放的目的地。fw = new FileWriter( "demo.txt" );//如果想对已有文件进行数据续写,创建文件时传递一个true参数,代表不覆盖已有的文件。并在已有文件的末尾处进行数据续写。//fw = new FileWriter("demo.txt",true);//调用write方法,将字符串写入到流中。fw.write( "JAVA Hello" );} catch (IOException e) {System. out .println( "catch:" +e.toString());} finally {try {//关闭流资源,但是关闭之前会刷新一次内部的缓冲中的数据。//将数据刷到目的地中。//fw.flush();//和flush区别:flush刷新后,流可以继续使用,close刷新后,会将流关闭。if (fw != null )fw.close();} catch (IOException e) {System. out .println(e.toString());
}}
}
既然close方法也可以刷新缓冲区,为什么,还要专门有一个flush方法。
jvm占用空间有限,不可能让一个比较大的数据完毕后,才刷新缓冲区。
close方法和flush方法的区别?
flush:刷新缓冲区,流对象还可以继续使用。
close:先刷新缓冲区,然后释放资源。流对象不可以被使用了
2、FileReader(文件字符输入流)
package com.File;
import java.io.*;
public class FileReaderDemo {
public static void main(String[] args) {//创建一个文件读取流对象,和指定名称的文件相关联。//要保证该文件是已经存在的,如果不存在,会发生异常FileNotFoundExceptionFileReader fr = null ;try {fr = new FileReader( "demo.txt" );//定义一个字符数组。用于存储读到字符。//该read(char[])返回的是读到字符个数。char [] buf = new char [1024];int ch = 0;//调用读取流对象的read方法。//read():一次读一个字符。而且会自动往下读。while ((ch=fr.read(buf))!=-1){//将char数组有效部分转换成字符串System. out .println( new String(buf,0,ch));}} catch (FileNotFoundException e) {System. out .println(e.toString());} catch (IOException e) {// TODO Auto-generated catch blockSystem. out .println(e.toString());} finally {if (fr != null )try {fr.close();} catch (IOException e) {System. out .println(e.toString());}}}
}
3、FileInputStream(文件字节输入流)和FileOutStream(文件字节输出流)
基本操作和字符流类型相同,但它不仅可以操作字符,还可以操作其他媒体文件,例如Copy一个Jpg或者Mp3文件。字节流可以不用刷新,因为数据的最基本单位就是字节,所以,可以直接把字节数据写入文件。
需求:将一个文本文件复制一份。
package com.File;
import java.io.*;
public class CopyDemo {
public static void main(String[] args) throws IOException {// TODO Auto-generated method stubcopy_1();copy_2();}//字节方法private static void copy_2() throws IOException {//创建输入流FileInputStream fis = new FileInputStream( "demo.txt" );
//创建输出流FileOutputStream fos = new FileOutputStream( "demo_2.txt" );byte [] bytes = new byte [1024];int num = 0;while ((num=fis.read(bytes)) != -1){fos.write(bytes,0,num);}}//字符方法private static void copy_1() throws IOException {FileReader fr = null ;FileWriter fw = null ;fr = new FileReader( "demo.txt" );fw = new FileWriter( "demo_1.txt" );char [] chars = new char [1024];int num = 0;while ((num = fr.read(chars)) != -1){fw.write(chars,0,num);}fw.flush();fr.close();fw.close();}}
三、缓冲流
为了提高效率而存在的, 减少物理读取次数, 缓冲流主要有:
BufferedInputStream 、BufferedOutputStream 、BufferedReader 、BufferedWriter , 并且
BufferedReader 提供了实用方法readLine(),可以直接读取一行,BufferWriter 提供了newLine()
可以写换行符。
1、
采用字符缓冲流改造文件复制代码
package com.File;
import java.io.*;
public class CopyDemo02 {
public static void main(String[] args) throws IOException {copy_1();}//字符方法private static void copy_1() throws IOException {BufferedReader br = null ;BufferedWriter bw = null ;br = new BufferedReader( new FileReader( "demo.txt" ));bw = new BufferedWriter( new FileWriter( "demo_b1.txt" ));String num = null ;while ((num = br.readLine()) != null ){bw.write(num);bw.newLine();}br.close();bw.close();}}
2、装饰设计模式:
当想要对已有的对象进行功能增强时,可以定义类,将已有对象传入,基于已有的功能,并提供加强功能。那么自定义的该类称为装饰类。
装饰类通常会通过构造方法接收被装饰的对象。并基于被装饰的对象的功能,提供更强的功能。
装饰模式比继承要灵活。避免了继承体系臃肿。而且降低了类于类之间的关系。装饰类因为增强已有对象,具备的功能和已有的是相同的,只不过提供了更强功能。所以装饰类和被装饰类通常是都属于一个体系中的。
例:
package com.File;
import java.io.*;class MyBufferedReader extends Reader{private Reader r ;MyBufferedReader(Reader r){this . r = r;}//模拟一下BufferedReader的readLine方法//可以一次读一行数据的方法。public String myReadLine() throws IOException{//定义一个临时容器。原BufferReader封装的是字符数组。//为了演示方便。定义一个StringBuilder容器。因为最终还是要将数据变成字符串。StringBuilder sb = new StringBuilder();int ch = 0;while ((ch= r .read())!=-1){if (ch== '\r' )continue ;if (ch== '\n' )return sb.toString();elsesb.append(( char )ch);}
if (sb.length()!=0)return sb.toString();return null ;}
/*覆盖Reader类中的抽象方法。
*/public int read( char [] cbuf, int off, int len) throws IOException{return r .read(cbuf,off,len) ;}
public void close() throws IOException{r .close();}public void myClose() throws IOException{r .close();}}
package com.File;
import java.io.*;
//装饰类class MyLineNumberReader extends MyBufferedReader{private int lineNumber ;MyLineNumberReader(Reader r){super (r);}//增强myReadLine方法,为其增加行号public String myReadLine() throws IOException{
lineNumber ++;return super .myReadLine();}public void setLineNumber( int lineNumber){this . lineNumber = lineNumber;}public int getLineNumber(){return lineNumber ;}}
public class MyLineNumberReaderDemo{public static void main(String[] args) throws IOException{FileReader fr = new FileReader( "AbstractDemo.java" );
MyLineNumberReader mylnr = new MyLineNumberReader(fr);
String line = null ;//mylnr.setLineNumber(100);//设置行号的初始值while ((line=mylnr.myReadLine())!= null ){System. out .println(mylnr.getLineNumber()+ "::" +line);}
mylnr.myClose();}}
LineNumberReader(Reader in)//使用默认输入缓冲区的大小创建新的行编号 reader。LineNumberReader此类定义了方法setLineNumber(int)
和getLineNumber()
,它们可分别用于设置和获取当前行号。
四、转换流
主要有两个:
InputStreamReader 主要是将字节流输入流转换成字符输入流
OutputStreamWriter 主要是将字节流输出流转换成字符输出流
1、
InputStreamReader
。需求:将键盘录入的字节流转换成字符流
package com.File;
import java.io.*;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {//获取键盘录入对象。InputStream in = System. in ;
//将字节流对象转成字符流对象,使用转换流。InputStreamReaderInputStreamReader isr = new InputStreamReader(in);//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReaderBufferedReader bufr = new BufferedReader(isr);String line = null ;while ((line=bufr.readLine())!= null ){if ( "over" .equals(line)){break ;}System. out .println(line.toUpperCase());}bufr.close();}
}
2、
OutputStreamWriter
package com.File;
import java.io.*;
public class TransStreamDemo {
public static void main(String[] args) throws IOException {//获取键盘录入对象。//InputStream in = System.in;
//将字节流对象转成字符流对象,使用转换流。InputStreamReader//InputStreamReader isr = new InputStreamReader(in);//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader//BufferedReader bufr = new BufferedReader(isr);BufferedReader bufr = new BufferedReader( new InputStreamReader(System. in ));//OutputStream out = System.out;//OutputStreamWriter osw = new OutputStreamWriter(out);//BufferedWriter bufw = new BufferedWriter(osw);// 为使用newLineBufferedWriter bufw = new BufferedWriter( new OutputStreamWriter(System. out ));String line = null ;while ((line=bufr.readLine())!= null ){if ( "over" .equals(line)){break ;}bufw.write(line.toUpperCase());bufw.newLine();//字符输出有缓存区,需要flushbufw.flush();}bufr.close();}
}
五、 流操作的基本规律
通过三个明确来完成:
1,明确源和目的。源:输入流。InputStream Reader目的:输出流。OutputStream Writer。2,操作的数据是否是纯文本。是:字符流。不是:字节流。
3,当体系明确后,在明确要使用哪个具体的对象。通过设备来进行区分:源设备:内存,硬盘。键盘目的设备:内存,硬盘,控制台。
1、需求分析:将一个文本文件中数据存储到另一个文件中。复制文件。
源:因为是源,所以使用读取流。InputStream Reader
是不是操作文本文件。
是!这时就可以选择Reader
这样体系就明确了。
接下来明确要使用该体系中的哪个对象。
明确设备:硬盘。上一个文件。
Reader体系中可以操作文件的对象是 FileReader
是否需要提高效率:是!。加入Reader体系中缓冲区 BufferedReader.
FileReader fr = new FileReader("demo.txt");
BufferedReader bufr = new BufferedReader(fr);
目的:OutputStream Writer
是否是纯文本。
是!Writer。
设备:硬盘,一个文件。
Writer体系中可以操作文件的对象FileWriter。
是否需要提高效率:是!。加入Writer体系中缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);
2、需求:将键盘录入的数据保存到一个文件中。
源:InputStream Reader
是不是纯文本?是!Reader
设备:键盘。对应的对象是System.in.
不是选择Reader吗?System.in对应的不是字节流吗?
为了操作键盘的文本数据方便。转成字符流按照字符串操作是最方便的。
所以既然明确了Reader,那么就将System.in转换成Reader。
用了Reader体系中转换流,InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗?需要!BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
FileWriter fw = new FileWriter("c.txt");
需要提高效率吗?需要。
BufferedWriter bufw = new BufferedWriter(fw);
3、扩展一下,想要把录入的数据按照指定的编码表(utf-8),将数据存到文件中。
目的:OutputStream Writer
是否是存文本?是!Writer。
设备:硬盘。一个文件。使用 FileWriter。
但是FileWriter是使用的默认编码表。GBK.
但是存储时,需要加入指定编码表utf-8。而指定的编码表只有转换流可以指定。
所以要使用的对象是OutputStreamWriter。
而该转换流对象要接收一个字节输出流。而且还可以操作的文件的字节输出流。FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("d.txt"),"UTF-8");
需要高效吗?需要。
BufferedWriter bufw = new BufferedWriter(osw);
所以,记住。转换流什么使用。字符和字节之间的桥梁,通常,涉及到字符编码转换时,需要用到转换流。
六、File
用来将文件或者文件夹封装成对象,
方便对文件与文件夹的属性信息进行操作 。File
对象可以作为参数传递给流的构造函数。
File类常见方法:
1,创建。
boolean createNewFile():在指定位置创建文件,如果该文件已经存在,则不创建,返回false。和输出流不一样,输出流对象一建立创建文件。而且文件已经存在,会覆盖。
boolean mkdir():创建文件夹。
boolean mkdirs():创建多级文件夹。
2,删除。
boolean delete():删除失败返回false。如果文件正在被使用,则删除不了返回falsel。
void deleteOnExit();在程序退出时删除指定文件。
3,判断。
boolean exists() :文件是否存在.
isFile():
isDirectory();
isHidden();
isAbsolute();
4,获取信息。
getName():
getPath():
getParent():
getAbsolutePath()
long lastModified()
long length()
需求:列出指定目录下文件或者文件夹,包含子目录中的内容。(以及删除)
package com.File;import java.io.*;public class listFile {
public static void main(String[] args) {File dir = new File( "F:\\360云盘\\视频\\51CTO下载-毕向东上课PPT源码" );//showDir(dir ,0);
removeDir( new File( "F:\\客户端\\zzz" ));}public static String getLevel( int level){StringBuilder sb = new StringBuilder();sb.append( "|--" );for ( int x=0; x<level; x++){//sb.append("|--");sb.insert(0, "| " );
}return sb.toString();}public static void showDir(File dir, int level){System. out .println(getLevel(level)+dir.getName());
level++;File[] files = dir.listFiles();for ( int x=0; x<files. length ; x++){if (files[x].isDirectory())showDir(files[x],level);elseSystem. out .println(getLevel(level)+files[x]);}}public static void removeDir(File dir){File[] files = dir.listFiles();for ( int x=0; x<files. length ; x++){if (files[x].isDirectory()) //判断是否是目录removeDir(files[x]);elseSystem. out .println(files[x].toString()+ ":-file-:" +files[x].delete()); //打印并删除文件}
System. out .println(dir+ "::dir::" +dir.delete()); //删除目录}
}
七、Properties
是hashtable的子类。它具备map集合的特点。而且它里面存储的键值对都是字符串。是集合中和IO技术相结合的集合容器。
该对象的特点:可以用于键值对形式的配置文件。
在加载数据时,需要数据有固定格式:键=值。例:Properties prop = new Properties();
FileInputStream fis = new FileInputStream("info.txt");
//将流中的数据加载进集合。
prop.load(fis);
prop.setProperty("wangwu","39");
FileOutputStream fos = new FileOutputStream("info.txt");
prop.store(fos,"haha");
prop.list(System.out);
fos.close();
fis.close();
八、打印流
该流提供了打印方法,可以将各种数据类型的数据都原样打印。
字节打印流:
PrintStream构造函数可以接收的参数类型:1,file对象。File2,字符串路径。String3,字节输出流。OutputStream
字符打印流:
PrintWriter构造函数可以接收的参数类型:1,file对象。File2,字符串路径。String3,字节输出流。OutputStream4,字符输出流,Writer。
import java.io.*;
class PrintStreamDemo
{
public static void main(String[] args) throws IOException
{
BufferedReader bufr =
new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new FileWriter("a.txt"),true);
String line = null;
while((line=bufr.readLine())!=null)
{
if("over".equals(line))
break;
out.println(line.toUpperCase());
//out.flush();
}
out.close();
bufr.close();
}
}
九、序列流(SequenceInputStream)
对多个流进行合并。
应用图片的合成
package com.File;
import java.io.*;import java.util.ArrayList;import java.util.*;
public class SequenceInputStreamDemo {
public static void main(String[] args) throws IOException {splitFile();merge();}//分割文件public static void splitFile() throws IOException{FileInputStream fis = new FileInputStream( "D:\\360\\360Downloads\\wpcache\\360wallpaper.jpg" );FileOutputStream fos = null ;byte [] buf = new byte [1024*100];int len = 0;int count = 0;while ((len=fis.read(buf))!=-1){fos = new FileOutputStream( "D:\\360\\360Downloads\\wpcache\\" +(count++)+ ".suipian" );fos.write(buf,0,len);fos.close();}fis.close();}
//合并public static void merge() throws IOException{ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();for ( int x=0;x<3; x++){al.add( new FileInputStream( "D:\\360\\360Downloads\\wpcache\\" +x+ ".suipian" ));}final Iterator<FileInputStream> it = al.iterator();Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){public boolean hasMoreElements(){return it.hasNext();}public FileInputStream nextElement(){return it.next();}};SequenceInputStream sis = new SequenceInputStream(en);FileOutputStream fos = new FileOutputStream( "D:\\360\\360Downloads\\wpcache\\hebing.bmp" );byte [] buf = new byte [1024];int len = 0;while ((len=sis.read(buf))!=-1){fos.write(buf, 0, len);}fos.close();sis.close();}}
十、对象流
对象流可以将Java 对象转换成二进制写入磁盘,这个过程通常叫做
序列化
,并且还可以从磁盘读出完整的Java 对象,而这个过程叫做
反序列化
。
对象流主要包括:ObjectInputStream 和ObjectOutputStream
序列化
必须实现序列化接口java.io.
Serializable
,该接口没有任何方法,
只是一种
标记接口
,标记这个类是可以序列化的
序列化是对内存中的数据。
静态不能被序列换
package com.File;
import java.io.*;
public class ObjectStreamDemo{public static void main(String[] args) throws Exception{//writeObj();readObj();}public static void readObj() throws Exception{ObjectInputStream ois = new ObjectInputStream( new FileInputStream( "obj.txt" ));
Person p = (Person)ois.readObject();
System. out .println(p);ois.close();}
public static void writeObj() throws IOException{ObjectOutputStream oos =new ObjectOutputStream( new FileOutputStream( "obj.txt" ));
oos.writeObject( new Person( "lisi0" ,399, "kr" ));
oos.close();}}
//实现Serializable接口,标记这个类是可以序列化的class Person implements Serializable{//定义类的序列号public static final long serialVersionUID = 42L;
private String name ;//采用transient 关键字修饰此属性,序列化时会忽略transient int age ;//静态不能被实例化,static String country = "cn" ;Person(String name, int age,String country){this . name = name;this . age = age;this . country = country;}public String toString(){return name + ":" + age + ":" + country ;}}
十一、管道流(
PipedInputStream
和
PipedOutputStream)
输入输出可以直接进行连接,通过结合线程使用
package com.File;import java.io.*;
class Read implements Runnable{private PipedInputStream in ;Read(PipedInputStream in){this . in = in;}@Overridepublic void run() {try {byte [] buf = new byte [1024];System. out .println( "读取前---没有数据阻塞" );int len = in .read(buf);System. out .println( "读取到数据---阻塞结束" );String s = new String(buf,0,len);System. out .println(s);in .close();} catch (IOException e){throw new RuntimeException( "管道读取失败" );}}}
class Write implements Runnable{private PipedOutputStream out ;Write(PipedOutputStream out){this . out = out;}@Overridepublic void run() {System. out .println( "开始写入数据,等待6秒后" );try {Thread. sleep(6000);out .write( "piped lai la" .getBytes());out .close();} catch (Exception e) {throw new RuntimeException( "管道流输出失败" );}}}public class PipedStreamDemo {
public static void main(String[] args) throws IOException {PipedInputStream in = new PipedInputStream();PipedOutputStream out = new PipedOutputStream();in.connect(out);Read r = new Read(in);Write w = new Write(out);new Thread(r).start();new Thread(w).start();}
}
十二、RandomAccessFile
该类不是算是IO体系中子类,而是直接继承自Object。但是它是IO包中成员。因为它具备读和写功能。内部封装了一个数组,而且通过指针对数组的元素进行操作。可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置。
其实完成读写的原理就是内部封装了字节输入流和输出流。
该类只能操作文件。而且操作文件还有模式:只读r,,读写rw等。
如果模式为只读 r。不会创建文件。会去读取一个已存在文件,如果该文件不存在,则会出现异常。
如果模式rw。操作的文件不存在,会自动创建。如果存则不会覆盖
import java.io.*;
class RandomAccessFileDemo
{
public static void main(String[] args) throws IOException
{
//writeFile_2();
//readFile();
//System.out.println(Integer.toBinaryString(258));
}
public static void readFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","r");
//调整对象中指针。
//raf.seek(8*1);
//跳过指定的字节数
raf.skipBytes(8);
byte[] buf = new byte[4];
raf.read(buf);
String name = new String(buf);
int age = raf.readInt();
System.out.println("name="+name);
System.out.println("age="+age);
raf.close();
}
public static void writeFile_2()throws IOException
{
//不会覆盖文件,只会覆盖文件中的数据
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.seek(8*0);
raf.write("周期".getBytes());
raf.writeInt(103);
raf.close();
}
public static void writeFile()throws IOException
{
RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");
raf.write("李四".getBytes());
raf.writeInt(97);
raf.write("王五".getBytes());
raf.writeInt(99);
raf.close();
}
}
十三、字符编码:
计算机底层是没有文本文件、图片文件之分的,它只记录每个文件的二进制序列。
常见的码表:
ASCII:美国标准信息交换码,用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。
UTF-8:最多用三个字节来表示一个字符。
字符流的出现方便操作字符,更重要的是加入了编码转换,通过转换流来完成的
InputStreamReader和OutputStreamWriter
举例说明:
package com.itheima.encode;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/*
* 基本的字符和字节流是实现不了编码问题的。
* 如果你想实现编码的处理,就必须使用转换流。
* OutputStreamWriter:如果没有指定编码,默认编码是GBK。
* 字符流 = 字节符 + 编码表
* 编码问题的解决方案:采用统一编码表。
*/
public class EncodeStream {
public static void main(String[] args) throws IOException {
// 使用的是默认的编码表
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw.txt"), "UTF-8"); // GBK,UTF-8
// FileWriter osw = new FileWriter("osw.txt");
osw.write("中国");
osw.close();
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"),"UTF-8");
char[] chs = new char[20];
int len = isr.read(chs);
String text = new String(chs,0,len);
System.out.println(text);
}
}
常见的码表:
ASCII:美国标准信息交换码,用一个字节的7位可以表示。
ISO8859-1:拉丁码表。欧洲码表用一个字节的8位表示。
GB2312:中国的中文编码表。
GBK:中国的中文编码表升级,融合了更多的中文文字符号。
Unicode:国际标准码,融合了多种文字。
UTF-8:最多用三个字节来表示一个字符。
字符流的出现方便操作字符,更重要的是加入了编码转换,通过转换流来完成的
InputStreamReader和OutputStreamWriter
举例说明:
package com.itheima.encode;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
/*
* 基本的字符和字节流是实现不了编码问题的。
* 如果你想实现编码的处理,就必须使用转换流。
* OutputStreamWriter:如果没有指定编码,默认编码是GBK。
* 字符流 = 字节符 + 编码表
* 编码问题的解决方案:采用统一编码表。
*/
public class EncodeStream {
public static void main(String[] args) throws IOException {
// 使用的是默认的编码表
// OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
// "osw.txt"));
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(
"osw.txt"), "UTF-8"); // GBK,UTF-8
// FileWriter osw = new FileWriter("osw.txt");
osw.write("中国");
osw.close();
InputStreamReader isr = new InputStreamReader(new FileInputStream(
"osw.txt"),"UTF-8");
char[] chs = new char[20];
int len = isr.read(chs);
String text = new String(chs,0,len);
System.out.println(text);
}
}
编码:字符串变成字节数组。
解码:字节数组变成字符串。
String-->byte[]; str.getBytes(charsetName);
byte[] -->String: new String(byte[],charsetName);