早期学习的时候写了一个demo,这里发出来记录一下
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
/*
* 打印流:
* 字节流打印流PrintStream(线程同步的,因为方法加了synchronize)
* 它可以写字节,也可以写字符串(底层用了字符缓冲流)
* 字符流打印流PrintWriter
*
* java.io.OutputStream
|- java.io.FilterOutputStream
|- java.io.PrintStream
已实现的接口: Closeable, Flushable, Appendable, AutoCloseable
特点: .PrintStream 永远不会抛出 IOException,因为它全部捕获了,通过内部的
public boolean checkError()刷新流并检查其错误状态,错误时返回true.
.只有写出数据的,没有读取数据的
.可以操作任意类型的数据
.可以启动自动刷新
.该流可以直接操作文本文件
哪些流对象是可以直接操作文本文件的呢?
FileInputStream
FileOutputStream
FileReader
FileWriter
PrintStream
PrintWriter...
字节流打印流PrintStream
1.构造方法:
PrintStream(File file)
创建具有指定文件且不带自动行刷新的新打印流。
PrintStream(File file, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(String fileName)
创建具有指定文件名称且不带自动行刷新的新打印流。
PrintStream(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新打印流。
PrintStream(OutputStream out)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush)
创建新的打印流。
PrintStream(OutputStream out, boolean autoFlush, String encoding) throws UnsupportedEncodingException
创建新的打印流。
//要设置自动刷新,只能接受字节流
2.字段:out 继承自过滤流FilterOutputStream(老二)
3.成员方法(代表):
public void write(byte[] buf, int off,int len)
public PrintStream append(CharSequence csq)
public PrintStream format(String format, Object... args)
public PrintStream printf(String format, Object... args)实际就是调用了上面的format
public void print(Object obj)
public void println(Object x)
public void println()//只换行
-------------------------------------------------
字符流打印流 PrintWriter
1.构造方法
PrintWriter(File file)
使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(File file, String csn) (本质)
创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
PrintWriter(String fileName)
创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName, String csn)
创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out)
根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush) (本质)
通过现有的 OutputStream 创建新的 PrintWriter。
//可以接受字符流对象
PrintWriter(Writer out)
创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush)
创建新 PrintWriter。
//可以接受字节流,字符流对象,并可设置自动刷新
2.字段:protected Writer out此 PrintWriter 的底层字符输出流
3.成员方法(代表):
public void write(char[] buf, int off, int len)
//跟字节流相比,直接写出字符串public void write(String s)
public PrintStream append(CharSequence csq)
public PrintStream format(String format, Object... args)
public PrintStream printf(String format, Object... args)实际就是调用了上面的format
public void print(Object obj)
public void println(Object x)
public void println()//只换行
两个打印流几乎是一样的,就构造方法字符打印流可以接受Writer,有一个可以直接写入字符串的方法
需求:
1,向文件IO测试1.txt添加任意类型数据
2,复制文本文件(带自动刷新和不带自动刷新的)
3,复制mp3
pw.println(line); //带自动刷新
//相当于:
bw.writer(line)
bw.newLine();
bw.flush();
注意:自动刷新
只有在调用 println、printf 或 format 的其中一个方法时才可能完成此操
也就是说,只要调用其中的一种方法,就可以使自动刷新生效.
这里说下刷新的问题:
一般在close关闭时,会自动刷新一次
在使用缓冲流的时候,有的文件需要循环几次读入,这时就需要在循环体内加入刷新,最后再关闭;
如果没有超过缓冲区,不用手写刷新;
*/
public class 打印流 {
public static void print() throws IOException{
//可以采用打印字符流实现
//设置一个自动刷新
PrintWriter pw=new PrintWriter(new FileWriter("IO测试1.txt"),true);
pw.write("hello");
pw.println();
pw.append('j');
pw.append("ava");
pw.println();
pw.println(true);
pw.println(12);
pw.println(10000l);
pw.println('a');
pw.println(3.14);
pw.printf("显示两位小数:%.2f \n", 2.345678);
pw.println("小明");
pw.close();
}
//1实现的复制文件
public static void copyFile1() throws IOException {
BufferedReader br=new BufferedReader(new FileReader("IO测试2.txt"));
//采用字符输出打印流
//底层使用的还是BufferedWriter,也就是说可以保证高效
PrintWriter pw=new PrintWriter("IO打印.txt");//不带自动刷新的
// PrintWriter pw=new PrintWriter("IO打印.txt","GBK");
String line=null;
while((line=br.readLine())!=null){
// pw.append(line);
// pw.write(line);
pw.println(line);
pw.flush();
}
System.out.println("ok");
br.close();
pw.close();
}
//打印流的简洁体现在复制文本文件的时候,复制其他文件还是要用原来的方法
public static void copyFile11() throws IOException {
BufferedReader br=new BufferedReader(new FileReader("IO测试2.txt"));
PrintWriter pw=new PrintWriter(new FileOutputStream("IO打印1.txt"),true);//带自动刷新的
String line=null;
while((line=br.readLine())!=null){
pw.println(line);
}
System.out.println("ok");
br.close();
pw.close();
}
//复制mp3
public static void copyMp3() throws IOException {
//采用缓冲字节输入流
InputStream is=new BufferedInputStream(new FileInputStream("D:\\轻音乐 - 雨的印记.mp3"));
//采用字节打印输出流
PrintStream ps=new PrintStream("F:\\copy.mp3");//不自动刷新
byte bys[]=new byte[1024];
int len=0;
while ((len=is.read(bys))!=-1) {
ps.write(bys, 0, len);
//这里不能使用println,因为它没有写出字符数组一部分的方法
ps.flush();
}
is.close();
ps.close();
System.out.println("ok");
}
public static void main(String[] args) throws IOException {
print();
// copyFile1();
// copyFile11();
// copyMp3();
}
}
jdk8之前最快的文本读取:Scanner
jdk8之后最快的应该是使用并行流
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.Scanner;
/*
* 最方便快速的文本写:Scanner(只能读取文本文件)
* 文本读:字符打印流
* 需求1:复制文本文件(文本格式就行,txt,java等)
* 需求2:复制mp3(不能用Scanner实现,它似乎只能操作文本文件) ,只能用字节缓冲流实现
* 需求3;筛选文件数据,
* 比如一个文本里面:姓名,年龄,成绩
* 注意:筛选的时候,Scanner读取的时候,文本的格式要一致,否则乱码
* 或者跳过while循环( 当使用Scanner sc=new Scanner(new File("D:\\IO测试2.txt"));)
* 这个构造方法时会跳过循环
* 所以:
* a.如果你知道要读取的文本格式,可以手动设置,默认的就不用设置
* b.如果你不知道文本格式(或者你懒的知道),那么需要先获取文本格式的编码,再进行读取
*
*那么如何得到编码格式?
* ×方法1:使用缓冲字符输入流(读取),不要用缓冲字符输出流(会清空内容),呵呵,你会发现只返回GBK,不管用
* 方法2;根据前三个字节判断常用的编码格式utf-8,GBK(ANSI),unicode,作为一个工具类
*
*Scanner 可以读取GBK格式等其他格式的文件
*/
public class 打印流结合Scanner {
private static void copyFile() throws IOException {
Scanner sc=new Scanner(new File("D:\\IO测试2.txt"));
PrintWriter pw=new PrintWriter("IO测试copy.txt");
while (sc.hasNext()) {
//读取一行,存储一行
// pw.write(sc.nextInt());
pw.println(sc.nextLine());
pw.flush();
}
sc.close();
pw.close();
System.out.println("ok");
}
//优化:使用try 自动close
private static void copyFile_1() {
try ( Scanner sc=new Scanner(new File("D:\\IO测试2.txt"));
PrintWriter pw=new PrintWriter(new FileOutputStream("IO测试copy.txt"),true);//自刷新
)
{
while (sc.hasNext()) {
pw.println(sc.nextLine());
// pw.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}
System.out.println("ok");
}
public static String getEncoding(File file) {
if (!file.exists()) {
System.out.println("文件不存在!");
System.exit(1);
}
String code="GBK";
InputStream is =null;
try {
//不能直接用字节数组,因为有的返回值超过了128
is = new BufferedInputStream(new FileInputStream(file));
int head[] = new int[3];
for (int i = 0; i < head.length; i++) {
head[i]=is.read();
}
if (head[0]==0xef&&head[1]==0xbb&&head[2]==0xbf) {
code="UTF-8";
}else if (head[0]==0xff&&head[1]==0xfe) {
code="Unicode";
}else if (head[0]==0xfe&&head[1]==0xff) {
code="Unicode big endian";
}else{
System.out.println("可能是GBK");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return code;
}
//筛选,默认的GBK格式时不用设置
private static void filter1() throws IOException {
Scanner sc=new Scanner(new FileInputStream("D:\\IO筛选测试GBK.txt"),"GBK");
while (sc.hasNext()) {
//默认空格作为分割符
String name=sc.next();
int age=sc.nextInt();
double score=sc.nextDouble();
System.out.printf("姓名:%s,年龄:%d,成绩:%.2f\n",name,age,score);
}
sc.close();
}
//如果我不知道文本格式,需要先获取编码格式
//经过测试发现:跟数据操作流一样,
//1.读取时,编码必须一致,否则报错InputMismatchException(模式不匹配)
//2.读取时,必须按照数据类型进行依次读取,否则报错
//如果是读取字符串,只要文件格式一致就可以滴
//
//经过查询字符集,发现Unicode big endian没有,估计不支持
//读取unicode时没有问题
//读取UTF-8出现一点问题,姓名:?小明,年龄:21,成绩:34.46,多读了一个乱码
//也就是Scanner可以读取其他的格式,但是容易出问题,用随机字符流来对基本类型数据进行操作比较好
//当然Scanner对字符串操作支持的比较好
private static void filter11() throws IOException {
// File file = new File("D:\\IO筛选测试unicode.txt");
File file = new File("D:\\IO筛选测试utf-8.txt");
String code = getEncoding(file);
Scanner sc = new Scanner(new FileInputStream(file), "UTF-8");
// while (sc.hasNext()) {
// String name = sc.next();
// int age = sc.nextInt();
// double score = sc.nextDouble();
// System.out.printf("姓名:%s,年龄:%d,成绩:%.2f\n", name, age, score);
// }
while (sc.hasNext()) {
// 0xef&&head[1]==0xbb&&head[2]==0xbf
// sc.skip("0xef0xbb0xbf");
// sc.skip("0xef|0xbb|0xbf");
// sc.skip("0xbf");
String name = sc.next();
int age = sc.nextInt();
double score = sc.nextDouble();
System.out.printf("姓名:%s,年龄:%d,成绩:%.2f\n", name, age, score);
}
sc.close();
}
public static void main(String[] args) throws IOException{
// copyFile();
// filter1();
filter11();
}
}