java IO
java流
Java中将输入输出抽象称为流,就好像水管,将两个容器连接起来。流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流.
输入流和输出流
根据数据的输入、输出方向的不同对而将流分为输入流和输出流。
- 输入流:InputStream和Reader
- 输出流:OutputStream和Writer
字符流和字节流
流序列中的数据既可以是未经加工的原始二进制数据,也可以是经一定编码处理后符合某种格式规定的特定数据。因此Java中的流分为两种:
- 字节流:InputStream和OutputStream(数据流中最小的数据单元是字节)
- 字符流:Reader和Writer(数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。)
Java 字节流与字符流的区别
字节流在操作时本身不会用到缓冲区(内存),是文件本身直接操作的,而字符流在操作时使用了缓冲区,通过缓冲区再操作文件;
以写文件的操作为主进行比较,在操作时字节流和字符流的操作完成之后都不关闭输出流。
使用字节流不关闭执行:文件中也依然存在了输出的内容,证明字节流是直接操作文件本身的;
使用字符流不关闭执行:程序运行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。
什么叫缓冲区?
可以简单地把缓冲区理解为一段特殊的内存。
某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。
在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。
Java流类的类结构图
Java IO的基本用法
Java IO :字节流
字节流对应的类应该是InputStream和OutputStream,而在我们实际开发中,我们根据不同的媒介类型选用相应的子类来处理
例1,用字节流写文件
public static void writeByteToFile(){
String hello= new String( "hello word!");
byte[] byteArray= hello.getBytes();
File file= new File( "E://tmp//writeByteToFile.txt");
//因为是用字节流来写媒介,所以对应的是OutputStream
//又因为媒介对象是文件,所以用到子类是FileOutputStream
OutputStream os;
try {
os = new FileOutputStream( file);
os.write( byteArray);
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
例2,用字节流读文件
public static void readByteFromFile(){
File file= new File( "E://tmp//writeByteToFile.txt");
byte[] byteArray= new byte[( int) file.length()];
//因为是用字节流来读媒介,所以对应的是InputStream
//又因为媒介对象是文件,所以用到子类是FileInputStream
InputStream is;
try {
is = new FileInputStream( file);
int size= is.read( byteArray);
System. out.println( "大小:"+size +";内容:" +new String(byteArray));
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Java IO :字符流
例3,用字符流读文件
public static void readCharFromFile() {
File file= new File( "E://tmp//writeByteToFile.txt");
//因为是用字符流来读媒介,所以对应的是Reader
//又因为媒介对象是文件,所以用到子类是FileReader
Reader reader;
try {
reader = new FileReader( file);
char [] byteArray= new char[( int) file.length()];
int size= reader.read( byteArray);
System. out.println( "大小:"+size +";内容:" +new String(byteArray));
reader.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
例4,用字符流写文件
public static void writeCharToFile(){
String hello= new String( "wahahahahahahaha");
File file= new File( "E://tmp//writeByteToFile.txt");
//因为是用字符流来读媒介,所以对应的是Writer,又因为媒介对象是文件,所以用到子类是FileWriter
Writer os;
try {
os = new FileWriter( file);
os.write( hello);
os.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
随机读取File文件
通过上面的例子我们已经知道,我们可以用FileInputStream(文件字符流)或FileReader(文件字节流)来读文件,这两个类可以让我们分别以字符和字节的方式来读取文件内容,但是它们都有一个不足之处,就是只能从文件头开始读,然后读到文件结束。
但是有时候我们只希望读取文件的一部分,或者是说随机的读取文件,那么我们就可以利用RandomAccessFile。RandomAccessFile提供了seek()
方法,用来定位将要读写文件的指针位置,我们也可以通过调用getFilePointer()
方法来获取当前指针的位置,具体看下面的例子:
例5,随机写入文件
public static void randomAccessFileWrite() {
// 创建一个RandomAccessFile对象
RandomAccessFile file;
try {
file = new RandomAccessFile( "E://tmp//writeByteToFile.txt", "rw");
// 通过seek方法来移动读写位置的指针
file.seek(10);
// 获取当前指针
long pointerBegin = file.getFilePointer();
// 从当前指针位置开始写
file.write( "HELLO WORD!HHHHHHH".getBytes());
long pointerEnd = file.getFilePointer();
System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" );
file.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
例6,随机读取文件
public static void randomAccessFileRead() {
// 创建一个RandomAccessFile对象
RandomAccessFile file;
try {
file = new RandomAccessFile( "E://tmp//writeByteToFile.txt", "rw");
// 通过seek方法来移动读写位置的指针
file.seek(10);
// 获取当前指针
long pointerBegin = file.getFilePointer();
// 从当前指针开始读
byte[] contents = new byte[1024];
file.read( contents);
long pointerEnd = file.getFilePointer();
System. out.println( "pointerBegin:" + pointerBegin + "\n" + "pointerEnd:" + pointerEnd + "\n" + new String(contents));
file.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
参考文献链接: http://blog.****.net/suifeng3051/article/details/48344587