学习JAVA的已经22天了,这不是第一次接触流的概念,但这之后还是有很多的混淆,今天的这篇博客,希望和大家有有些更近一步的交流。
简单介绍:
1、流机制在java和C++中是一种重要的机制,通过流,我们可以很方便地操作文件,内存,IO设备等。流都包含与java.io包中。
2、流来源与UNIX中管道的概念,管道就是传递的源源不断的字节流,进而可以在不同的两端传递数据。所以,流一般都是有一个源端和目的端,一般是从外部设备中读取然后传到内存中,等到需要时,再从内存中取出来。
1、流的分类:(从内存的角度来讲)
按照流向:输入流、输出流
操作单元:字节流、字符流
设计模式:基础流、包装流
来源分类:文件流、内存流、网络流、控制台流(System.out System.in)
内存流:内存与内存之间传递数据,内存流。
2、字节流
1、 在内存当中,都是以字节的方式传递的,常用的类:
InputStream OutputStream
一般是对文件的操作:
FileInputStream(输入流,从文件或外部设备到内存)、FileOutputStream(输出流,从内存到其他地方),一般都是对文件的操作。
FileInputStream infile = new FileInputStream("myfile.txt");
FileOutputStream outfile = new FileOutputStream("results.txt");
注意:FileInputStream操作的文件必须是存在并且可读的,FileOutputStream操作的文件如果不存在,会自动创建,如果存在,则文件必须是可覆盖的。
涉及到的一个重定向:
static void setIn(InputStream in)
static void setOut(PrintStream out)
3、字符流
字符流主要是用来处理字符的。Java采用16位的Unicode来表示字符串和字符,对应的字符流按输入和输出分别称为readers和writers。
一般是对文件的操作:
对文件操作的字符流有FileReader/FileWriter
4、转换流
转换流:java提供将字节流转化为字符流读写方式的
仅有字符流InputStreamReader/OutputStreamWriter。其中,InputStreamReader需要与InputStream“套接”,OutputStreamWriter需要与OutputStream“套接”。(装饰者设计模式)
5、缓冲流
缓冲流:缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高了读写效率,同时增加了一些新的方法。
字节缓冲流有BufferedInputStream/BufferedOutputStream,字符缓冲流有BufferedReader/BufferedWriter,字符缓冲流分别提供了读取和写入一行的方法ReadLine和NewLine方法。
对于输出地缓冲流,写出的数据,会先写入到内存中,再使用flush方法将内存中的数据刷到硬盘。所以,在使用字符缓冲流的时候,一定要先flush,然后再close,避免数据丢失。
6、内存流
在之前讲解FileInputStream 和 FileOutputStream 的时候所有的操作的目标是文件,那么如果现在假设有一些临时的信息要求通过IO操作的话,那么如果将这些临时的信息保存在文件之中则肯定很不合理,因为操作的最后还要把文件再删除掉,所以此时的IO中就提供了一个内存的操作流,通过内存操作流输入和输出的目标是内存。
使用ByteArrayOutputStream 和 ByteArrayInputStream 完成内存的操作流。其使用方法和InputStream 、OutputStream类似,一个个的读取数据。
public static void main(String[] args) {
byte[] bytes = {0,0,1,2};
try (DataInputStream dis = new DataInputStream(new FileInputStream("aaa"));){
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int length;
byte[] temp = new byte[1024];
while ((length = dis.read(temp)) != -1) {
baos.write(temp,0,length);
}
System.out.println(baos.toString("GBK"));
} catch (Exception e) {
e.printStackTrace();
}
}
7、控制台流
System.in System.out
8、常用的
1、还有一个关键字比较重要,transient,由于修饰实现了Serializable接口的类内的属性,被该修饰符修饰的属性,在以对象流的方式输出的时候,该字段会被忽略。
9、打印流:
public static void main(String[] args) throws FileNotFoundException {
// TODO Auto-generated method stub
File file = new File ("D:"+File.separator+"demo.txt");
PrintStream output = new PrintStream(new FileOutputStream(file));
output.print("Hello");
output.print(" World");
output.println("abco");
output.println(1.0);
output.close();
}
10、RandomAccessFile
RandomAccessFile它不属于IO流
只有RandomAccessFile才有seek方法,而这个方法也只适用于文件。
具体用法:
11、数据流DataInputStream
DataInputStream和DataOutputStream分别继承自InputStream和OutputStream,需要“套接”在InputStream和OutputStream类型的节点流之上。
它可以保证“无论数据来自何种机器,只要使用一个DataInputStream收取这些数据,就可用本机正确的格式保存它们.
简单案例:
对文件的简单读写:
public static void main(String[] args) {
try(FileInputStream fos = new FileInputStream("res/test")) {
InputStreamReader isr = new InputStreamReader(fos);
BufferedReader br = new BufferedReader(isr);
PrintStream out = new PrintStream(System.out);
String str;
while ((str = br.readLine()) != null) {
out.println(str);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
另附案例:阿拉伯数字转化为中文数字
package org.xiaohong.work;
import java.io.*;
public class Test02 {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream("res/test"), "UTF-8"));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("res/trans.txt"), "UTF-8"))
) {
String str;
int percent = 0;
while ((str = br.readLine()) != null) {
bw.write(trans_wan(Integer.parseInt(str)));
bw.newLine();
Thread.sleep(100);
percent++;
System.out.print("\r[");
for (int i = 0; i < 20; i++) {
if (i < percent / 5) {
System.out.print("=");
} else if (i == percent / 5) {
System.out.print(">");
} else {
System.out.print(" ");
}
}
System.out.print("]");
System.out.printf("\t%.2f%%", (float) percent);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private static String trans_wan(int num) {
StringBuilder builder = new StringBuilder();
if (num / 10000 > 0) {
builder.append(trans(num / 10000)).append("万");
}
boolean flag = true;
if (num % 1000 > 0) {
String trans = trans(num % 10000);
// 判断前四位末尾是否是0
if (num / 10000 % 10 == 0) {
builder.append("零");
flag = false;
}
if (builder.length() > 0) {
// 判断后四位是否需要添加零
if (trans.indexOf("千") == 2 && flag) {
builder.append("零");
}
}
builder.append(trans);
}
if (builder.length() == 0) {
builder.append("零");
}
return builder.toString();
}
private static String trans(int num) {
// 中文大写数字数组
String[] numeric = new String[]{"零", "一", "二", "三", "四", "五", "六", "七", "八", "九"};
StringBuilder builder = new StringBuilder();
builder.append(numeric[num / 1000]).append("千")
.append(numeric[num / 100 % 10]).append("百")
.append(numeric[num / 10 % 10]).append("十")
.append(numeric[num % 10]);
int index = -1;
while ((index = builder.indexOf(numeric[0], index + 1)) != -1) {
if (index < builder.length() - 1) {
builder.deleteCharAt(index + 1);
}
}
index = 0;
while ((index = builder.indexOf("零零", index)) != -1) {
builder.deleteCharAt(index);
}
if (builder.length() > 1) {
if (builder.indexOf(numeric[0]) == 0) {
builder.deleteCharAt(0);
}
if (builder.lastIndexOf(numeric[0]) == builder.length() - 1) {
builder.deleteCharAt(builder.length() - 1);
}
}
if (builder.indexOf("一十") == 0) {
builder.deleteCharAt(0);
}
return builder.toString();
}
}