二、 IO流的体系
三、关于路径
四、FileReader读取数据
五、FileWriter输出数据
六、FileInputStream和FileOutputStream进行文件复制
七、字节缓冲流复制文件
八、转换流
8-1编码表
九、系统流,标准流
一、流的分类
按照处理类型分
二、 IO流的体系
分类 | 字节输入流 | 字节输出流 | 字符输入流 | 字符输出流 | 备注 |
---|---|---|---|---|---|
访问文件 | FileInputStream | FileOutPutStream | FileReader | FileWriter | 节点流/常用 |
访问数组 | ByteArrayInputStream | ByteArrayOutputStream | CharArrayReader | CharArrayWriter | |
访问管道 | PipedInputStream | PipedOutPutStream | PipedReader | PipedWriter | |
访问字符串 | StringReader | StringWriter | |||
缓冲流 | BufferedInputStream | BufferedOutputStream | BufferedReader | BufferedWriter | 常用 |
转换流 | InputStreamReader | OutPutStreamWriter | 常用 | ||
对象流 | ObjectInputStream | ObjectOutputSteam | |||
打印流 | PrintStream | PriterWriter | |||
推回输入流 | PushbackInputStream | PushbackReader | |||
特殊流 | Data Input Stream | DataOutPutStream | 只能处理属性,处理对象要用对象流 |
- 节点流就是能直接操作的流,与节点流对应的是处理流
- 字符流操作的是char,字节流操作的是byte
三、关于路径
public static void main(String[] args) {
File file = new File("hello.text");
System.out.println(file.getAbsoluteFile());
File file1 = new File("/hello.text");
System.out.println(file1.getAbsoluteFile());
}
/*
F:\code\myInnerclass\hello.text
F:\hello.text
*/
总结:可以看出加上/是一个绝对路径,不加/是一个相对路径,相对当前项目。虽然这个和Linux类似,但是还是要注意一下
四、FileReader读取数据
@Test
public void testFileReader() {
FileReader fileReader = null;
try {
File file = new File("src/hello.text");
System.out.println(file.getAbsoluteFile());
fileReader = new FileReader(file);
//读入一个字符,如果返回-1表示没读到,字符对应的int
int data;
while ((data = fileReader.read())!=-1){
System.out.print((char)data);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fileReader!=null)
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/*
F:\code\myInnerclass\src\hello.text
你好
我好
大家好
*/
第二种方式
@Test
public void testFileReader1(){
FileReader fileReader = null;
try {
File file = new File("src/hello.text");
fileReader = new FileReader(file);
char[] charbuf = new char[5];
int len;
/* while ((len = fileReader.read(charbuf))!=-1){
for (int i = 0; i < len; i++) {
System.out.print(charbuf[i]);
}
}
*/
while ((len = fileReader.read(charbuf))!=-1){
String str = new String(charbuf,0,len);
System.out.print(str);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileReader!=null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意:read()和read(char[]) 的返回值是不一样的,read()的返回是当前字符在字符集中的int表示,而read(char[])返回的是char[]中已经使用的长度。
五、FileWriter输出数据
@Test
public void testFileWriter() {
FileWriter fw = null;
try {
File file = new File("src/hello1.text");
//fw = new FileWriter(file);
fw = new FileWriter(file,true);
fw.write("i hava a dream\n");
fw.write("i hava a dream too\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fw != null)
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
注意:new FileWriter(file,true),true代表追加写,换行在windows中用\n
六、FileInputStream和FileOutputStream进行文件复制
@Test
public void testFileInOutStream(){
FileInputStream fis = null;
FileOutputStream fos = null;
try {
File file = new File("src/1.jpg");
File file1 = new File("src/2.jpg");
fis = new FileInputStream(file);
fos = new FileOutputStream(file1);
byte[] buf = new byte[1024];
int len;
while ((len=fis.read(buf))!=-1){
fos.write(buf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fos!=null){
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fis!=null){
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
七、字节缓冲流复制文件
@Test
public void testBufferedInOutPutStream(){
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
File file = new File("src/1.jpg");
File file1 = new File("src/3.jpg");
FileInputStream fileInputStream = new FileInputStream(file);
FileOutputStream fileOutputStream = new FileOutputStream(file1);
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
byte[] buf = new byte[1024];
int len;
while ((len = bufferedInputStream.read(buf))!=-1){
bufferedOutputStream.write(buf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (bufferedInputStream!=null){
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufferedOutputStream!=null){
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
注意:
- 包装流会自动关闭内部(父类)的流,因为本身继承父类的close方法,其实也是调用父类的关闭方法
- 缓冲输出流有一个flush方法,用来刷新流,如果流关闭会自动调用flush方法
public void close() throws IOException { try (OutputStream ostream = out) { flush(); } }
- 缓冲流默认大小是8k
public class BufferedInputStream extends FilterInputStream { private static int DEFAULT_BUFFER_SIZE = 8192;
字符缓冲流复制文件
@Test public void testBufferedReaderWriter(){ BufferedReader bufferedReader = null; BufferedWriter bufferedWriter = null; try { bufferedReader = new BufferedReader(new FileReader(new File("src/hello.text"))); bufferedWriter = new BufferedWriter(new FileWriter(new File("src/hello3.text"))); String str; while((str=bufferedReader.readLine())!=null){ bufferedWriter.write(str); bufferedWriter.newLine(); } } catch (IOException e) { e.printStackTrace(); } finally { if (bufferedReader!=null){ try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedWriter!=null){ try { bufferedWriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
注意:
- BufferedReader比Readerer多出来一个readLine方法
- BufferedWriter有一个newLine方法
八、转换流
转换流,顾名思义就是对流进行转换,提供了InputStreamReader和OutputStreamWriter这两种流,那为啥要叫InputStreamReader而不是ReaderInputStream,说明是把字节流输入流转换为字符输入流
通过图像可以看出:输入就是字节转字符,输出就是字符转字节
那么转换流主要解决啥子问题呢?编码
说道编码就要说说编码表
8-1编码表
常见的编码表有以下几种
编码 | 描述 |
---|---|
ASCII | 存放128个字符,占用1个字节,给英文使用够了 |
ISO-8859-1 | 占用1个字节,存放256,英文加上拉丁 |
GB2312 | 最多占用2个字节,存放中文够了,可能占用1个字节,如果最高位位1则表示占用2个字节,否则占用1个字节 |
GBK | 最多2个字节,中文简体+繁体。存储细节和GB2312类似 |
utf-8 | 1-4个字节,万国码,一般中文3个字节, 4个字节11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 3个字节 1110xxxx 10xxxxxx 10xxxxxx 2个字节 110xxxxx 10xxxxxx 1个字节 0xxxxxxx |
ANSI | 这个不是编码,这个在notepad中代表以当前系统语言来识别,英文ISO8859-1。中文GBK |
@Test
public void testInputStreamReaderOutPutStreamWriter(){
InputStreamReader inputStreamReader = null;
OutputStreamWriter outputStreamWriter = null;
try {
inputStreamReader = new InputStreamReader(new FileInputStream(new File("src/hello.text")),"UTF-8");
outputStreamWriter = new OutputStreamWriter(new FileOutputStream(new File("src/helloTo.text")),"GBK");
char[] buf = new char[1024];
int len;
while((len=inputStreamReader.read(buf))!=-1){
outputStreamWriter.write(buf,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStreamWriter!=null){
try {
outputStreamWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (inputStreamReader!=null){
try {
inputStreamReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
总结:
- InputStreamReader和OutputStreamWriter都是可以在构造函数中指定编码集的。如果没有指定编码按照下面的代码解析看会先获取文件的编码,如果文件没有编码,按照UTF-8解析
public static Charset defaultCharset() {
if (defaultCharset == null) {
synchronized (Charset.class) {
String csn = AccessController.doPrivileged(
new GetPropertyAction("file.encoding"));
Charset cs = lookup(csn);
if (cs != null)
defaultCharset = cs;
else
defaultCharset = forName("UTF-8");
}
}
return defaultCharset;
}
九、系统流,标准流
static PrintStream | err “标准”错误输出流。 |
---|---|
static InputStream | in “标准”输入流。 |
static PrintStream | out “标准”输出流。 |
是System类中的流
System.in对应这Scanner
System.out就是常用System.out.println 打印到控制台
常用的方法
static void |
setIn(InputStream in) 重新分配“标准”输入流。 |
---|---|
static void |
setOu(PrintStream out) 重新分配“标准”输出流。 |
其他流基本不用,就不再介绍了。
来自为知笔记(Wiz)