1.简介:
1.1分类
java的IO流分两种流 :字节流和字符流
字节流 InputStream OutputStream
字符流 Reader Writer
他们都是抽象类
具体实现
字节流 FileInputStream FileOutputStream
字符流 FileReader FileWriter
字符流 Reader Writer
他们都是抽象类
具体实现
字节流 FileInputStream FileOutputStream
字符流 FileReader FileWriter
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点,如果是关系到中文(文本)的,用字符流较好。
所有文件的储存是都是字节(byte)的储存,在磁盘上保留的并不是文件的字符而是先把字符编码成字节,再储存这些字节到磁盘。在读取文件(特别是文本文件)时,也是一个字节一个字节地读取以形成字节序列.
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。
字节流可用于任何类型的对象,包括二进制对象,而字符流只能处理字符或者字符串;
字节流提供了处理任何类型的IO操作的功能,但它不能直接处理Unicode字符,而字符流就可以。
1.2转换
1.2.1读取文件从字节流输入到字符流输入
// 定义一个指向D:/TEXT.TXT 的字节流
FileInputStream fileInputStream = new FileInputStream("d:/text.txt");
//字节流转换成InputStreamReader
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
//InputStreamReader 转换成缓冲流:bufferedReader
BufferedReader bufferedReader = new BufferedReader(inputSteamReader);
可以把读出来的内容赋值给字符
String ss = new String();
String s;
while((s = bufferedReader.readLine())!=null){
ss += s;
}
1.2.2写入文件 从字节流输出到字符流输出
//定义一个指向D:/TEXT.TXT文件
FileOutputStream fileOutputStream = new FileOutputStream("d:/text.txt");
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream);
BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
bufferedWriter.write(s);
bufferedWriter.close();
outputStreamWriter.close();
fileOutputStream.close();
2字节流与字节缓冲流
在I/O类库中,java.io.InputStream和java.io.OutputStream分别表示字节输入流和字节输出流,它们都是抽象类,不能实例化,数据流中的最小单位是字节,所以叫做字节流。
2.1 InputStream中的读取数据的方法如下:
1 、int read()
功能:读取一个字节的数据,并且返回读到得数据,如果返回-1,则表示读到输入流的末尾。
2、int read(byte[] b)
功能:从输入流中读取一定量的字节,并将其存储在字节数组b中,返回实际读取的字节数,如果返回-1,则表示读到输入流的末尾。
3、int read(byte[] b, int off, int len)
功能:将数据读入一个字节数组,同时返回读取的实际字节数,如果返回-1,则表示读到输入流的末尾。off指定在数组b中存放数据的起始偏移位置,len指定读取的最大字节数。
4、available()
功能:返回此输入流下一个方法调用可以不受阻塞地从此输入流读取或跳过的估计字节数。
5、close()
功能:关闭输入流,释放这个流的相关资源。
2.2 OutputStream中写入数据的方法如下:
1 、int write(int b)
功能:将b的最低的一个字节写入此输入流,其他三个字节丢弃。
2、int write(byte[] b)
功能:将指定的字节数组b写入此输入流。
3、int write(byte[] b, int off, int len)
功能:将指定byte数组中从偏移量off开始的len个字节写入输入流。
4、flush()
功能:刷新此输入流并强制写出所有缓冲的输出字节数。
5、close()
功能:关闭输出流,释放这个流的相关资源。
①字节数组输入流:
package com.iotest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
public class ByteArryInputStreamDemo {
public static void main(String[] args) throws IOException {
String str = "abcdefghijk";
byte[] strBuf = str.getBytes(); //字符串转换成字节数组
ByteArrayInputStream bais = new ByteArrayInputStream(strBuf);
int data = bais.read(); //从字节数组输入流读取字节
while(data!=-1){
char upper = Character.toUpperCase((char)data);
System.out.print(upper+" ");
data = bais.read();
}
bais.close();
}
}
程序运行结果:A B C D E F G H I J K
②字节数组输出流:
package com.iotest;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public class ByteArrayOutputStreamDemo {
public static void main(String[] args) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String s = "welcome to use ByteArrayOutputStreamDemo";
byte[] buf = s.getBytes();
baos.write(buf); //将指定的byte数组写到字节数组输出流中
System.out.println(baos.toString()); //将字节数组输出流内容转换成字符串输出
//将字节数组输出流中的内容复制到字节数组中
byte[] b = baos.toByteArray();
for (int i = 0; i < b.length; i++) {
System.out.print((char)b[i]);
}
baos.close();
}
}
程序运行结果:
welcome to use ByteArrayOutputStreamDemo
welcome to use ByteArrayOutputStreamDemo
③文件输入输出流的使用
package com.iotest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
//复制图片
public class FileInputStreamDemo {
public static void main(String[] args) throws IOException {
File file = new File("F:\\shar\\test\\logo17.gif");
FileInputStream fis = new FileInputStream(file); //创建一个输入流
//创建一个输出流,后面一个参数true表示追加,原有内容不会被清除,默认为false
FileOutputStream fos = new FileOutputStream("F:\\shar\\test\\logo18.gif",false);
int ch = 0;
//方式一
/*while((ch=fis.read()) != -1){
fos.write(ch);
}*/
//方式二
/*byte[] b = new byte[1024];
while((ch=fis.read(b)) != -1){
fos.write(b,0,ch);
}*/
//方式三
byte[] b = new byte[fis.available()];
fis.read(b); //首先把fis的内容读到字节数组b里面
fos.write(b);//再把字节数组b的内容通过输出流写到指定文件
//关闭流
fos.close();
fis.close();
}
}
④管道流的使用:
一个PipedInputStream对象必须和一个PipedOutputStream对象进行连接从而产生一个通信管道。通常一个线程从管道输出流写入数据,另一个线程从管道输入流中读取数据。当线程A执行管道输入流的read()方法时,如果暂时没有数据,这个线程就会被阻塞,只有当线程B想管道输出流写了数据后,线程A才会恢复运行。
package com.iotest;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/*
* 管道流
*/
class Sender extends Thread{
private PipedOutputStream out = new PipedOutputStream();
public PipedOutputStream getOut() {
return out;
}
@Override
public void run() {
String s = "hello world";
try {
out.write(s.getBytes());
out.close();
} catch (Exception e) {
// TODO: handle exception
}
}
}
public class Receiver extends Thread{
private PipedInputStream in;
public Receiver(Sender sender) throws IOException {
in = new PipedInputStream(sender.getOut());
}
@Override
public void run() {
try {
int data;
while((data=in.read())!=-1){
System.out.print((char)data);
}
in.close();
} catch (Exception e) {
// TODO: handle exception
}
}
public static void main(String[] args) throws IOException {
Sender sender = new Sender();
Receiver r = new Receiver(sender);
sender.start();
r.start();
}
}
⑤缓冲流的使用:
package com.iotest;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class TestPrime {
private BufferedInputStream bis = null;
private BufferedOutputStream bos = null;
String fileName = "F:\\shar\\test\\test2.txt";
static int s,p;
//判断是否是质数
public boolean isPrime(int n){
for(int i=2;i<=n/2;i++){
if(n%i == 0){
return false;
}
}
return true;
}
void printPrime(int m) throws IOException{
//将字节流转缓冲流
bos = new BufferedOutputStream(new FileOutputStream(fileName));
int j = 0;
for (int i = 2; i < m; i++) {
if(isPrime(i)){
j++;
if(j%s == 0){
String s = String.valueOf(i)+" ";
bos.write(s.getBytes());
bos.write("\r\n".getBytes());
}else{
String s = String.valueOf(i)+" ";
bos.write(s.getBytes());
}
}
}
bos.flush();
bos.close();
}
void getPrime() throws IOException{
//将字节流转缓冲流
bis = new BufferedInputStream(new FileInputStream(fileName));
int c = bis.read();
while(c != -1){
char ch = (char)c;
System.out.print(ch);
c = bis.read();
}
}
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
TestPrime t = new TestPrime();
p = 100;
s = 10;
t.printPrime(p);
t.getPrime();
}
}
如果不用缓冲流的话,程序是读一个数据,写一个数据。这样在数据量大的程序中非常影响效率。 缓冲流作用是把数据先写入缓冲区,等缓冲区满了,再把数据写到文件里。这样效率就大大提高了。
3字符流与字符缓冲流
java中字符流主要都是继承于Reader和Writer两个抽象类。用于对字符文本的读写操作。
①转换类流
package com.iotest;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class ConverseStreamDemo {
public static void main(String[] args) {
String s = "F:\\shar\\test\\test3.txt";
try {
//将字节流转为字符流
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(s));
osw.write("中国北京");
System.out.println(osw.getEncoding());
osw.close();
osw = new OutputStreamWriter(new FileOutputStream(s,true),"GB2312");
osw.write("中国北京");
System.out.println(osw.getEncoding());
osw.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
//将字节流转为字符流
InputStreamReader isr = new InputStreamReader(new FileInputStream(s),"GB2312");
int c;
while((c=isr.read()) != -1){
System.out.print((char)c);
}
System.out.println();
isr.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
②FileReader和FileWriter
package com.iotest;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用flush()将流数据刷到目标里,这时流还存活着,还可以继续使用该流进行别的操作。
* close()虽然也有flush()的效果但是这时流已经死了,你如果想继续使用流的话就必须在此建立流
*/
public class MutiplicationTable {
public static void main(String[] args) throws IOException {
String s = "F:\\shar\\test\\test5.txt";
FileWriter fw = new FileWriter(s);
FileReader fr = new FileReader(s);
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
String str = i + "*" + j + "=" + i*j + " ";
fw.write(str);
}
fw.write("\r\n");
/*flush是指强行将输出流中的数据写到文件里面去。如果写到这里的话就是一行一行的写入文件
*最好每写完一部分就刷新一次,如果最后刷新的话可能会造成数据的丢失
*/
fw.flush();
}
//如果又不写flush()又不写close(),则不会写入任何内容到文本里。只是写到了缓冲区
//fw.flush(); 写到这里的话就是所有的内容一起写进文件
//fw.close(); close之前会调用flush()
//读字符输入流的数据
int c;
while ((c=fr.read())!=-1) {
System.out.print((char)c);
}
}
}
③BufferedReader和BufferedWriter
package com.iotest;
import java.io.BufferedOutputStream;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
public class PrimeNumber {
BufferedWriter bw = null;
String fileName = "F:\\shar\\test\\test7.txt";
//判断是否是质数
public boolean isPrime(int n){
for(int i=2;i<=n/2;i++){
if(n%i == 0){
return false;
}
}
return true;
}
void printPrime(int m) throws IOException{
//将字节流转缓冲流
bw = new BufferedWriter(new FileWriter(fileName));
int j = 0;
for (int i = 2; i < m; i++) {
if(isPrime(i)){
j++;
String s = String.valueOf(i);
String s1 = s + " ";
bw.write(s1); //写入文本文件
if(j==10){
j = 0;
bw.newLine(); //写入一个行分隔符
bw.flush(); //强制刷新
}
}
}
bw.close();
}
public static void main(String[] args) throws IOException {
PrimeNumber pn = new PrimeNumber();
pn.printPrime(100);
}
}
④PrintWriter
package com.iotest;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
public class PrintWriterDemo {
public static void main(String[] args) throws IOException {
int A = 0; //千位
int B = 0; //百位
int C = 0; //十位
int num = 0;
String fileName = "F:\\shar\\test\\test8.txt";
FileWriter fw = new FileWriter(fileName); //字符输出流
PrintWriter pw = new PrintWriter(fw); //将字节输出流转为PrintWriter
for (int i = 1000; i < 10000; i++) {
A = i/1000;
B = i/100 % 10;
C = i/10 % 10;
if(i%11==0 && A == B+C){
pw.print(i+" ");
if(++num % 7 == 0){
pw.println(); //写入回车换行
pw.flush(); //强制刷新流
}
}
}
fw.close();
}
}
⑤标准IO
package com.iotest;
import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Scanner;
public class PackStardIO {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
PrintWriter o = new PrintWriter(System.out); //包装标准输出
String s;
while((s=br.readLine())!=null && s.length()!=0){
o.println(s.toUpperCase());
//o.flush(); //一定要强制刷新让其输出来,否则不会输出
}
}
}
package com.iotest;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
public class StandardIORedirect {
public static void main(String[] args) throws IOException {
PrintStream console = System.out;
BufferedInputStream in = new BufferedInputStream(new FileInputStream("C:\\Documents and Settings\\01\\桌面\\Test\\src\\com\\iotest\\StandardIORedirect.java"));
PrintStream out = new PrintStream(new BufferedOutputStream(new FileOutputStream("F:\\shar\\test\\test9.txt")));
System.setIn(in); //对标准输入流重定向
System.setOut(out);
System.setErr(out);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s;
while((s=br.readLine())!=null){ //从BufferedReader中读取一行数据
System.out.println(s);
}
out.close();
System.setOut(console);
}
}
⑥随即访问文件类
package com.iotest;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class RandomRW {
public static void main(String[] args) throws IOException {
RandomAccessFile raf = new RandomAccessFile("F:\\shar\\test\\test10.dat","rw");
final int DOUBLE_SIZE = 8;
for (int i = 0; i < 10; i++) {
raf.writeDouble(i);
System.out.print(" " + (double)i);
}
System.out.println();
raf.close();
RandomAccessFile raf1 = new RandomAccessFile("F:\\shar\\test\\test10.dat","rw");
raf1.seek(3*DOUBLE_SIZE); //找到某个位置
raf1.writeDouble(300); //往该位置插入数据
raf1.seek(5*DOUBLE_SIZE);
raf1.writeDouble(500);
raf1.close();
RandomAccessFile raf2 = new RandomAccessFile("F:\\shar\\test\\test10.dat","r");
for (int i = 0; i < 10; i++) {
System.out.print(" "+raf2.readDouble());
}
raf2.close();
}
}