java的IO操作:字节流与字符流操作
流的概念
程序中的输入输出都是以流形式,流中保存的实际上都是字节文件。
字节流与字符流
字节流的操作:
1)输入:inputStream,
2)输出:outPutStream;
字符流的操作:
1)输入主要使用:write类。
2)输出主要使用:reader类。
内容操作就四个类。
操作流程:
使用File类操作一定有路径问题,注意分隔符:
实际上四个操作类都是抽象类(区别接口,抽象类的成员都是抽象,并且只能单继承,接口可以有全局变量,但是接口可以多继承)
IO操作属于资源操作,对于资源操作,操作最后必须关闭,否则有可能出现未知错误。
字节流
字节流主要操作byte类型数据,以byte数组为准,注意操作类为字节输出流:outputStream,字节输入流:inputStream,类。
Byte是字节,肯定使用字节流操作,所有的数据基本都可以使用byte数组表示出来。
OutputStream类
字节输出流的最大父类:定义如下:
public abstract class OutputStream extends Object implements Closeable ,Flushable;
Closeable表示可以关闭的操作,因为程序最后要关闭。
Flushable表示刷新,清空内存中数据。
此类是抽象类,所以要想使用此类,必须要通过子类实例化父类对象。
那么要操作的是一个文件,则可以使用FileOutputStream类,通过向上转型之后,可以为OutputStream实例化。
FileOutputStream构造方法:
public FileOutputStream( File file) throws FielNotFoundException
可见FileOutputStream需要操作File类的对象,并且有异常处理。
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象,注意下面是通过向上转型,实例化父类对象。
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
out.write(b) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
1)因为FielOutputStream有异常,wire()方法也有异常,为了节省操作,可以在主方法抛出异常,不处理
2)输出字符串:可以先用方法 getBytes()一次性读取字符串到字节数组中,然后再把字节数组输出。
3)OutputStream的实例对象调用write(byte []b)方法,把数组输出。
4)在操作时候,如果文件本身不存在,就会为用户自动创建新文件。
在操作输出流的时候也可以使用write(int i)的方式写出数据。
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
for(int i=0;i<b.length;i++){ // 采用循环方式写入
out.write(b[i]) ; // 每次只写入一个内容
}
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
以上操作在输入数据后,以前的数据不存在。因为在IO操作中默认是将其覆盖。如果要想执行追加功能,必须设置追加操作。
找到FileOutputStream类:
public FileOutputStream(File file,bool append)throws FileNotFoundException
在构造方法中,如果append的值设为true,表示在文件的末尾追加。
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f,true) ; // 此处表示在文件末尾追加内容
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
for(int i=0;i<b.length;i++){ // 采用循环方式写入
out.write(b[i]) ; // 每次只写入一个内容
}
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
上面是在末尾追加,没换行,如果要换行,在要添加的文子前面,使用“\r\n”完成。
如:String str="\r\n在这里追加";
package Thread1; import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream; public class demo1 {
// 所有的异常直接抛出,程序中不再进行处理
public static void main(String args[]) throws Exception{
File f=new File("D:\\outputStream.txt");
OutputStream out=new FileOutputStream(f,true);
String str="\r\n在这里追加";
byte[]b=str.getBytes();
out.write(b);
out.close();
}
};
运行结果:
字节输入流InputStream
定义:public abstract class inputStream extends Object implements Clossablle;
与OutputStream类似,也是抽象类,必须依靠子类,如果从文件读取,肯定是FileInputStream;
构造方法:
public FileInputStream(File file) throws FileNotFoundException
要处理异常,参数需要File对象,向上转型。
以read(byte[] b)形式读取到数组中。
package Thread1; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream; public class demo1 {
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "outputStream.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input=null; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ; // 所有的内容都读到此数组之中
input.read(b) ; // 读取内容
// 第4步、关闭输出流
input.close() ; // 关闭输出流
System.out.println("内容为:" + new String(b)) ; // 把byte数组变为字符串输出
}
};
运行结果:
内容为:hello moto在这里追加
在这里追加
1)定义一个byte类型的数组对象,用于读取从File类的指定文件的内容。
2)InputStream通过子类,利用多态性,向上转型,实例化对象。
3)InputStream对象调用read(byte b[])方法,把File中的内容读取给b[]数组。
此刻虽然读取出来了,但是存在问题,文件没有这么大,但是开辟了这么大空间,浪费内存。
能不能根据文件大小开辟数组空间?
如果要想知道文件大小,直接使用File类即可。f.length()方法获得文件的大小,注意同时要类型转换。
package Thread1; import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream; public class demo1 {
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "outputStream.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[(int)f.length()] ; // 数组大小由文件决定
int len = input.read(b) ; // 读取内容
// 第4步、关闭输出流
input.close() ; // 关闭输出流\
System.out.println("读入数据的长度:" + len) ;
System.out.println("内容为:" + new String(b)) ; // 把byte数组变为字符串输出
}
};
运行结果:
读入数据的长度:32
内容为:hello moto在这里追加
在这里追加
new String(b),因为读取的时候是从字符类型先转化成byte类型,所以输出要转换成String类型。
这里其实是String类的构造方法,相当于实例化了一个String类的对象,生成了一个String 变量。
以上是利用byte数组形式读取文件。read(byte [] b)
另外一个常用的读取方法read();字节一个个的读
abstract int read()
从输入流中读取数据的下一个字节
注意:read()方法的返回结果是int类型,所以对于字节需要转化类型,
package 类集;
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo04{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[(int)f.length()] ; // 数组大小由文件决定
for(int i=0;i<b.length;i++){
b[i] = (byte)input.read() ; // 读取内容
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流\
System.out.println("内容为:" + new String(b)) ; // 把byte数组变为字符串输出
}
};
以上操作只适合知道输入流大小的时候,如果现在不知道大小呢?
package 类集;
import java.io.File ;
import java.io.InputStream ;
import java.io.FileInputStream ;
public class InputStreamDemo05{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ; // 数组大小由文件决定
int len = 0 ;
int temp = 0 ; // 接收每一个读取进来的数据
while((temp=input.read())!=-1){ //这里先把字节读取出来,赋值给temp,如果temp不等于-1,表示还有内容,文件没有读完
b[len] = (byte)temp ;
len++ ;
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流\
System.out.println("内容为:" + new String(b,0,len)) ; // 把byte数组变为字符串输出
}
};
当不知道读取的内容有多大的时候,就只能通过以读取的内容是否为-1为读完的标志。
这个是常用的字节流操作方法:
InputStream input = null ; // 准备好一个输入的对象
input = new FileInputStream(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
byte b[] = new byte[1024] ; // 数组大小由文件决定
int len = 0 ;
int temp = 0 ; // 接收每一个读取进来的数据
while((temp=input.read())!=-1){ //这里先把字节读取出来,赋值给temp,如果temp不等于-1,表示还有内容,文件没有读完
b[len] = (byte)temp ;
len++ ;
}
字符流操作
字符输入流:Writer类
字符输出流:Reader类。
Writer类
常用方法:
字符流比字节流操作好在一点,就是可以直接输出字符串了。不用跟之前一样进行转换操作。
代码实例:
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串,注意,这里不用跟字节流操作一样转换成Byte数组类型。
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
使用字符流默认情况下依然覆盖已有文件,要想追加,则在FileWriter上加一个追加标记即可。
package 类集;
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f,true) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "\r\nLIXINGHUA\r\nHello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.close() ; // 关闭输出流
}
};
字符输入流:Reader()
常用方法
以字符数组形式读取出数组。
package 类集;
import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo01{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Reader input = null ; // 准备好一个输入的对象
input = new FileReader(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
char c[] = new char[1024] ; // 所有的内容都读到此数组之中
int len = input.read(c) ; // 读取内容
// 第4步、关闭输出流
input.close() ; // 关闭输出流
System.out.println("内容为:" + new String(c,0,len)) ; // 把字符数组变为字符串输出
}
};
输出结果:
内容为:hello fsdfsdfshello
LIXINGHUA
Hello World!!!
也可以以循环方式,通过文件是否读到底判断。
import java.io.File ;
import java.io.Reader ;
import java.io.FileReader ;
public class ReaderDemo02{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "test.txt") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Reader input = null ; // 准备好一个输入的对象
input = new FileReader(f) ; // 通过对象多态性,进行实例化
// 第3步、进行读操作
char c[] = new char[1024] ; // 所有的内容都读到此数组之中
int temp = 0 ; // 接收每一个内容
int len = 0 ; // 读取内容
while((temp=input.read())!=-1){
// 如果不是-1就表示还有内容,可以继续读取
c[len] = (char)temp ;
len++ ;
}
// 第4步、关闭输出流
input.close() ; // 关闭输出流
System.out.println("内容为:" + new String(c,0,len)) ; // 把字符数组变为字符串输出
}
};
字符流与字节流的区别
字节和字符使用非常相似,有哪些不同呢?
1,字节流不会用到缓存,字符流会用到缓存。
通过代码验证字节流使用到了缓存。
字节流操作:
package 类集;
import java.io.File ;
import java.io.OutputStream ;
import java.io.FileOutputStream ;
public class OutputStreamDemo05{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
OutputStream out = null ; // 准备好一个输出的对象
out = new FileOutputStream(f) ; // 实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
byte b[] = str.getBytes() ; // 只能输出byte数组,所以将字符串变为byte数组
out.write(b) ; // 写入数据
// 第4步、关闭输出流
// out.close() ; // 关闭输出流
}
};
结果在指定目录成功输出内容。
在使用字节流操作中,即使没有关闭,最终也可以输出。
字符流操作:
package 类集;
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
// out.close() ; // 此时,没有关闭
}
};
运行结果:为空。
以上操作没有输出任何内容,所有的内容现在保存在缓冲区当中,如果执行关闭的时候,会强制性的刷新缓冲区,所以可以把内容输出。
abstract void close()
关闭此流,但要先刷新它。
如果现在没有关闭的话,也可以强制调用刷新方法。
abstract void flush()
刷新该流的缓冲。
package 类集;
import java.io.File ;
import java.io.Writer ;
import java.io.FileWriter ;
public class WriterDemo03{
public static void main(String args[]) throws Exception{ // 异常抛出,不处理
// 第1步、使用File类找到一个文件
File f= new File("d:" + File.separator + "te.text") ; // 声明File对象
// 第2步、通过子类实例化父类对象
Writer out = null ; // 准备好一个输出的对象
out = new FileWriter(f) ; // 通过对象多态性,进行实例化
// 第3步、进行写操作
String str = "Hello World!!!" ; // 准备一个字符串
out.write(str) ; // 将内容输出,保存文件
// 第4步、关闭输出流
out.flush() ; // 强制性清空缓冲区中的内容
// out.close() ;
}
};
此时成功将内容写入指定路径下文件中。
开发中是使用字节流好还是字符流好。
在所有的硬盘中保存文件或进行传输的时候,都是以字节的方式进行的,包括图片,视频等多媒体也是以字节进行。
而字符是只有在内存中才会形成的,所以使用字节的时候是最多的。
操作范例:文件拷贝
操作的时候可以按照如下格式进行:
java Copy 源文件 目标文件
如果要采用以上的格式,则肯定要使用初始化参数的形式,输入两个路径。所以此时必须对输入的参数个数进行验证,判断其是否为2,
是使用字节流还是字符流呢,肯定使用字节流,因为万一拷贝的是图片呢?
要完成拷贝程序,有两种方式:
实现一,将源文件中内容全部读取进来,之后一次性写入到目标文件。
实现二,边读边写。
很明显第二种方式更好。
package 类集;
import java.io.* ;
public class Copy{
public static void main(String args[]){
if(args.length!=2){ // 判断是否是两个参数
System.out.println("输入的参数不正确。") ;
System.out.println("例:java Copy 源文件路径 目标文件路径") ;
System.exit(1) ; // 系统退出
}
File f1 = new File(args[0]) ; // 源文件的File对象
File f2 = new File(args[1]) ; // 目标文件的File对象
if(!f1.exists()){
System.out.println("源文件不存在!") ;
System.exit(1) ;
}
InputStream input = null ; // 准备好输入流对象,读取源文件
OutputStream out = null ; // 准备好输出流对象,写入目标文件
try{
input = new FileInputStream(f1) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
try{
out = new FileOutputStream(f2) ;
}catch(FileNotFoundException e){
e.printStackTrace() ;
}
if(input!=null && out!=null){ // 判断输入或输出是否准备好
int temp = 0 ;
try{
while((temp=input.read())!=-1){ // 开始拷贝
out.write(temp) ; // 边读边写
}
System.out.println("拷贝完成!") ;
}catch(IOException e){
e.printStackTrace() ;
System.out.println("拷贝失败!") ;
}
try{
input.close() ; // 关闭
out.close() ; // 关闭
}catch(IOException e){
e.printStackTrace() ;
}
}
}
}
java的IO操作:字节流与字符流操作的更多相关文章
- java学习笔记之IO编程—字节流和字符流
1. 流的基本概念 在java.io包里面File类是唯一一个与文件本身有关的程序处理类,但是File只能够操作文件本身而不能操作文件的内容,或者说在实际的开发之中IO操作的核心意义在于:输入与输出操 ...
- java IO之字节流和字符流-Reader和Writer以及实现文件复制拷贝
接上一篇的字节流,以下主要介绍字符流.字符流和字节流的差别以及文件复制拷贝.在程序中一个字符等于两个字节.而一个汉字占俩个字节(一般有限面试会问:一个char是否能存下一个汉字,答案当然是能了,一个c ...
- java IO的字节流和字符流及其区别
1. 字节流和字符流的概念 1.1 字节流继承于InputStream OutputStream, 1.2 字符流继承于InputStreamReader OutputStre ...
- java IO通过字节流,字符流 读出写入
一:通过字节流操作数据的写入,读出 /** * 通过字节流写入和读出 * @param args */ public static String filePath = "G:" + ...
- Java中常用的字节流和字符流
IO流(输入流.输出流) 字节流.字符流 1.字节流: InputStream.OutputStream InputStream抽象了应用程序读取数据的方式: OutputStream抽象了应用程序写 ...
- IO(字节流、字符流)
第1章 字节流 在前面的学习过程中,我们一直都是在操作文件或者文件夹,并没有给文件中写任何数据.现在我们就要开始给文件中写数据,或者读取文件中的数据. 1.1 字节输出流OutputStream ...
- 吴裕雄--天生自然JAVAIO操作学习笔记:字节流与字符流操作
import java.io.* ; public class Copy{ public static void main(String args[]){ if(args.length!=2){ // ...
- java:I/O 字节流和字符流
字节流 InputStream和OutputStream的子类:FileInputStream 和 FileOutputStream 方法: int read(byte[] b,int off,int ...
- [Day23]IO(字节流、字符流)
1.字节流 1.1 字节输出流OutputStream-抽象类,表示输出字节流的所有类的超类 (1)void close() 关闭此输出流并释放与此流相关的所有系统资源 (2)void flush() ...
随机推荐
- (二)shell变量
(1)自定义变量 定义变量 变量名=变量值 变量名必须以字母或下划线开头,不能数字开头,区分大小写,ip=114.114.114.114 引用变量: $变量名 ${变量名} 查看变量: echo $变 ...
- django URL参数在view中传递和Template的反向解析方式
一. URL参数在view中传递 1.带参数名:通过named group方式传递指定参数,语法为: (?P<name>pattern), name 为传递参数的名称,pattern代表所 ...
- HDU 6324.Problem F. Grab The Tree-博弈(思维) (2018 Multi-University Training Contest 3 1006)
6324.Problem F. Grab The Tree 题目看着好难,但是题解说的很简单,写出来也很简单.能想出来就是简单的,想不出来就难(讲道理,就算是1+1的题目,看不出来就是难的啊). 和后 ...
- Python与数据结构[3] -> 树/Tree[2] -> AVL 平衡树和树旋转的 Python 实现
AVL 平衡树和树旋转 目录 AVL平衡二叉树 树旋转 代码实现 1 AVL平衡二叉树 AVL(Adelson-Velskii & Landis)树是一种带有平衡条件的二叉树,一棵AVL树其实 ...
- 遇见requestAnimationFrame
今天,在读javascript异步编程的js事件深入理解部分的时候,了解到了requestAnimationFrame 这个api,在这里记录一下. 原文: setTimeout 和 setInter ...
- poj2155
poj2155 题意 二维区间更新,单点查询. 分析 二维线段树. 也可以用二维树状数组去做,维护矩阵前缀和. code #include<cstdio> using namespace ...
- [BZOJ 2964] Boss单挑战
Link:https://www.lydsy.com/JudgeOnline/problem.php?id=2964 Algorithm: 一道很新颖的背包问题 此题每个状态要维护的量巨多,而转移方式 ...
- 洛谷 P1452 Beauty Contest
题目背景 此处省略1W字^ ^ 题目描述 贝茜在牛的选美比赛中赢得了冠军”牛世界小姐”.因此,贝西会参观N(2 < = N < = 50000)个农场来传播善意.世界将被表示成一个二维平面 ...
- java web(学习笔记)项目路径问题
最近刚接触java web特别是是关于项目路径这一块很晕,就把自己遇到的一些疑惑和理解写下来. 首先贴上路径,这里用的是eclipse. 其中我们要注意看WebContent目录,这是web程序的根目 ...
- 如何提高码农产量,基于ASP.NET MVC的敏捷开发框架之工作流开发随笔三
前言 “厂长,APP的那几个功能都差不多了,接下来要做工作流,工作流这东西我完全没概念啊.” “查尔斯,一般来说工作流就是指将指定的数据.文件.任务按照预定的规则进行传递流转.比如说你要请假,拿个请假 ...