还有字节流、字符流
1、字节流:
(1)InputStream:抽象了应用程序读取数据的方式
(2)OutputStream:抽象了应用程序写 出数据的方式
2)EOF = End 读到-1就读到结尾
3)输入流基本方法
int b = in.read();读取一个字节无符号填充到int低八位.-1是EOF
in.read(byte[] buf) 读取数据填充到字节数组buf
in.read(byte[] buf,int start, int size)读取数据到字节数组buf从buf的start位置开始存放size长度分数据
4)输出流基本方法
out.write(int b)写出一个byte到流,b的低8位
out.write(byte[] buf)将buf字节数组都写到流
out.write(byte[] buf, int start,int size) 字节数组buf从start位置开始写size长度的字节到流
5)FileInputStream--->具体实现了在文件上读取数据
FileInputStream的使用
// 读取指定文件内容,按照16进制输出到控制台,并且每输出10个byte换行,单字节读取不适合大批量文件读取。
public static void printHex(String fileName) throws IOException {
// 把文件作为字节流进行读操作
FileInputStream in = new FileInputStream(fileName);
int b, i = 1;
while ((b = in.read()) != -1) {
if (b <= 0xf) {
// 单个数前面补0
System.out.print("0");
}
// 将整型b转换成16进制表示的字符串
System.out.print(Integer.toHexString(b) + " ");
if (i++ % 10 == 0) {
System.out.println();
}
}
in.close();
}
字节流之文件输入流FileInputStream操作 II
/**
* 批量读取,对大文件而言效率高,也是我们最常用的读文件的方式【重点】
* @param fileName
* @throws IOException
*/
public static void printHexByByteArray(String fileName)throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[8 * 1024];
/*从in中批量读取字节,放入到buf这个字节数组中,
* 从第0个位置开始放,最多放buf.length个
* 返回的是读到的字节的个数
*/
/*int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j = 1;
for(int i = 0; i < bytes;i++){//注意这不用buf.length是因为可能数组内存不够大,所以定为有效长度。
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}*/
Ps:当字节数组不够大,一次性读不完文件时怎么办?
int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length))!=-1){
for(int i = 0 ; i < bytes;i++){
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
}
in.close();
}
6)FileOutputStream 实现了向文件中写出byte数据的方法
7)FileOutputStream创建时若文件不存在,则新建该文件;若文件存在但未追加,则删除后在新建
FileOutputStream---->继承了OutputStream,实现了向文件中写出byte数据的方法
FileOutputStream out = new FileOutputStream(filename)//如果该文件不存在则直接创建,如果不存在则删除后创建
复制文件:
FileOutputStream out = new FileOutputStream(filename,true)//如果存在则追加
out.write('A')//写出字符A的低八位
例子:write方法写一个int整数
int a=10
out.write(a>>>24);out.write(a>>>16);out.write(a>>>8);out.write(a);
写字符
byte[] gbk="中国".getBytes("gbk")
out.write(gbk)
out.close()
批量写入
int bytes=0
while((bytes=in.read(buf,0,buf.length))!=0){
for(int i=0;i<bytes;i++)
System.out.print(Integer.toHexString(buf[i]&0xff)+" ")
}
in.close()
复制一个文件:
FileInputStream in=new FileInputStream(filename1)
FileOutputStream out=new FileOutputStream(filename2)
byte[] buf= new byte[8*1024]
int b
while((b=in.read(buf,0,buf.length))!=-1){
out.write(buf,0,b)
out.flush
}
in.close()
out.close()
字节流之文件输出流FileOutputStream操作 I
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//如果该文件不存在,则直接创建,如果存在,删除后创建
FileOutputStream out = new FileOutputStream("demo/out.dat");
//如果该文件不存在,则直接创建,如果存在,在该文件后追加内容
//FileOutputStream out = new FileOutputStream("demo/out.dat",true);
out.write('A');//写出了'A'的低八位
out.write('B');//写出了'B'的低八位
int a = 10;//write只能写八位,那么写一个int需要些4次每次8位
out.write(a >>> 24);
out.write(a >>> 16);
out.write(a >>> 8);
out.write(a);
byte[] gbk = "中国".getBytes("gbk");//如果平台本身就是gbk编码方式,则可以省略转换,最好还是写上,因为移植的时候就无需担心出现乱码情况。
out.write(gbk);
out.close();
IOUtil.printHex("demo/out.dat");
}
字节流之文件输出流FileOutputStream操作 II
/**
* 文件拷贝,字节批量读取
* @param srcFile//源文件
* @param destFile//因为目标文件不存在则会自动创建,所以无需if判断
* @throws IOException
*/
public static void copyFile(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(destFile);
byte[] buf = new byte[8*1024];
int b ;
while((b = in.read(buf,0,buf.length))!=-1){
out.write(buf,0,b);
out.flush();//最好加上(也可以不写);刷新此输出流并强制写出所有缓冲的输出字节。
}
in.close();
out.close();
}
8)DataOutoutStream/DataInputStream
对“流”功能的扩展,可以 更加方便的读取int,long,字符等类型数据
DataOutoutStream中
writeInt()/writeDouble()/writeUTF()
事例:
public class DosDemo{
public static void main(String[] args)throws IOException{
String file = "demo/dos.dat";
DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));
dos.writeInt(10);
dos.writeInt(-10);
dos.writeLong(10L);
dos.writeDouble(10.5);
dos.writeUTF("中国"); //采用utf-8编码写出
dos.writeChars("中国"); //采用utf-16be编码写出
dos.close();
}
}
DataOutputStream和DataInputStream就是对InputStream和OutputStream进行了包装,使得我们对基本数据类型的读写操作变得更加的方便。
9)BufferedInputStream & BufferedOutputStream
这两个流类为IO提供了带缓冲区的操作,一般打开文件进行写入或读取操作时,都会加上缓冲,这种流模式提供了IO的性能
从应用程序中把数据放入文件,相当于将一缸水倒入到另一个缸中:
FIleOutputStream--->write()方法相当于一滴一滴地将水转移
DataOutputStream--->writeXxx()方法会方便一些,相当于一瓢一瓢将水转移
BufferedOutputStream--->write方法更方便,相当于一瓢一瓢先放入桶中,再从桶中倒入到缸中,性能更高一些
bos.flush();//刷新缓冲区,
/**
* 进行文件的拷贝,利用带缓冲的字节流
* @param srcFile
* @param destFile
* @throws IOException
*/
public static void copyFileByBuffer(File srcFile,File destFile)throws IOException{
if(!srcFile.exists()){
throw new IllegalArgumentException("文件:"+srcFile+"不存在");
}
if(!srcFile.isFile()){
throw new IllegalArgumentException(srcFile+"不是文件");
}
BufferedInputStream bis = new BufferedInputStream(
new FileInputStream(srcFile));
BufferedOutputStream bos = new BufferedOutputStream(
new FileOutputStream(destFile));
int c ;
while((c = bis.read())!=-1){//非单个字节读取,一次性读一定的内容(填满缓冲区大小为止,默认8M大小)
bos.write(c);
bos.flush();//刷新缓冲区,一定要写,否则写入不进去;Ps:读取的时候无需flush,写入的时候最好要或有些地方一定要flush。
}
bis.close();
bos.close();
}
拷贝速度
使用缓冲字节流复制确实是最快的方式,但对于小文件10M以下的文件体现不出优势,对于百兆文件正确使用,时间可以控制到50ms内。视频中的缓冲字节流使用有错误,复制文件最快的做法是将批量读取到的字节数组使用缓冲写入到文件,在机器性能范围内字节数组越大越快。在循环写入的过程中不需要使用flush,缓冲输入流在关闭的时候会将所有缓冲区的数据全部写入文件,使用flush刷新缓冲就失去了缓冲的意义。最后关闭IO流和文件流应该在finally中关闭,否则IO异常时执行不到close语句,IO流仍然没有关闭。
java 文件写入:
1,创建需要写入的字符串
2,创建文件句柄:File file = new File("文件路径")
3,判断文件是否存在,如果不存在就创建!:if(file.exists())
{
file .createNewFile()
}
4,创建读取对象:FileWriter fw = new Filewriter( file.getAbsoluteFile());
5, 创建缓存对象 接收读取对象:BufferedWriter bf = new BufferedWriter(fw);
6, 缓存对象的写入方法,并调用声明的需要写入的字符串对象:bf.Writer(声明的需要写入的字符串对象)
7,关闭缓存写入对象: bf.close();
8, 注意此处应有IO对象的异常需要捕获!