JavaSE入门学习43:文件传输基础之I/O流(二)

时间:2023-02-15 07:30:42

        三RandomAccessFile类的的使用

        RandomAccessFile类是java提供的对文件内容的访问类,既可以读文件,也可以写文件。RandomAccessFile类

支持随机访问文件,可以访问文件的任意位置。

        RandomAccessFile类的构造方法:

JavaSE入门学习43:文件传输基础之I/O流(二)

        RandomAccessFile类中的方法:

JavaSE入门学习43:文件传输基础之I/O流(二)

JavaSE入门学习43:文件传输基础之I/O流(二)

JavaSE入门学习43:文件传输基础之I/O流(二)

        (1)java文件模型

        在硬盘上的文件是byte byte byte存储的,是数据的集合。

        (2)打开文件

        有两种模式"rw"(读写),"r"(只读)。例如下面的构造:

        RandomAccessFile raf = new RandomAccessFile(file,"rw");

        文件指针,打开文件时指针在开头,即pointer=0;

        (3)写方法

        raf.write(int)--->只写一个字节(后8位),同时指针指向下一个位置,准备再次写入。

        (4)读方法

        int b=raf.read()--->读一个字节

        (5)文件读写完成后一定要关闭(Oracle官方说明)。

        实例代码:

<span style="font-size:18px;">import java.io.*;
import java.util.*;

public class RafDemo{
public static void main(String[] args) throws IOException{
File demo = new File("E:\\Java\\JavaSE\\IO\\demo");
if(!demo.exists()){
demo.mkdir();
}
File file = new File(demo,"raf.dat");
if(!file.exists()){
file.createNewFile();
}

//读写操作
RandomAccessFile raf = new RandomAccessFile(file, "rw");
//指针的位置
System.out.println("未写入之前的指针初始位置:"+raf.getFilePointer());

raf.write('A');//只写了一个字节
System.out.println("第一次写入后的指针位置:"+raf.getFilePointer());
raf.write('B');

int i = 0x7fffffff;
//用write()方法每次只能写一个字节,如果要把i写进去就得写4次
raf.write(i >>> 24);//高8位
raf.write(i >>> 16);
raf.write(i >>> 8);
raf.write(i);
System.out.println("第六次写入后的指针位置:"+raf.getFilePointer());

//可以直接写一个int
raf.writeInt(i);

//一个中文占用2个字节
String s = "中";
byte[] gbk = s.getBytes("gbk");
raf.write(gbk);
System.out.println("第八次写入后的字节长度为:"+raf.length());

//读文件,必须把指针移到头部
raf.seek(0);
//一次性读取,把文件中的内容都读到字节数组中
byte[] buf = new byte[(int)raf.length()];
raf.read(buf);
//以字符串的方式输出
System.out.println(Arrays.toString(buf));
//以十六进制的方式输出
for(byte b : buf){
System.out.print(Integer.toHexString(b & 0xff)+" ");
}
//关闭读写操作
raf.close();
}
}</span>

        运行结果:

JavaSE入门学习43:文件传输基础之I/O流(二)

        四字节流的使用

        Java中IO流是输入/输出流,也分为字节流和字符流。

        (1)字节流

        1)InputStream抽象类和OutputStream抽象类

        InputStream抽象类抽象了应用程序读取数据的方式;OutputStream抽象类抽象了应用程序写出数据的方式 。

        2)EOF = End表示的含义是读到-1就读到结尾

        3)输入流基本方法

        int  b = in.read();//读取一个字节无符号填充到int低八位.-1是EOF

        in.read(byte[] buf) 

        in.read(byte[] buf,int start,int 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类继承了InputStream抽象类。

        FileInputStream类中的方法:

JavaSE入门学习43:文件传输基础之I/O流(二)

        实例代码1:

<span style="font-size:18px;">import java.io.*;

public class IOUtil{
/*
* 读取指定文件内容,按照十六进制输出到控制台
* 并且每输出10个byte换行
* 单字节读取不适合大文件,大文件效率很低
*/
public static void printHex(String fileName) throws IOException{
//把文件作为字节流进行读操作
FileInputStream in = new FileInputStream(fileName);
int b ;
int i = 1;
while((b = in.read())!=-1){
if(b <= 0xf){
//单个数前面补0
System.out.print("0");
}
//将整型b转换为十六进制表示的字符串
System.out.print(Integer.toHexString(b)+" ");
if(i++%10==0){
System.out.println();
}
}
//关闭读写流
in.close();
}

public static void main(String[] args){
try{
IOUtil.printHex("E:\\Java\\JavaSE\\IO\\FileUtils.java");
}catch(IOException e){
e.printStackTrace();
}
}
}</span>

        运行结果:

JavaSE入门学习43:文件传输基础之I/O流(二)

        实例代码2:

<span style="font-size:18px;">import java.io.*;

public class IOUtil{
/*
* 读取指定文件内容,按照十六进制输出到控制台
* 并且每输出10个byte换行
* 单字节读取不适合大文件,大文件效率很低
*/
public static void printHex(String fileName) throws IOException{
//把文件作为字节流进行读操作
FileInputStream in = new FileInputStream(fileName);
int b ;
int i = 1;
while((b = in.read())!=-1){
if(b <= 0xf){
//单个数前面补0
System.out.print("0");
}
//将整型b转换为十六进制表示的字符串
System.out.print(Integer.toHexString(b)+" ");
if(i++%10==0){
System.out.println();
}
}
//关闭读写流
in.close();
}

public static void printHexByByteArray(String fileName) throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[20 * 1024];
/*从in中批量读取字节,放入到buf这个字节数组中,
* 从第0个位置开始放,最多放buf.length个
* 返回的是读到的字节的个数
*/
int bytes = in.read(buf,0,buf.length);//一次性读完,说明字节数组足够大
int j = 1;
for(int i = 0; i < bytes;i.print("0");
if(buf[i] <= oxf){
System.out
}
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
in.close();
}

public static void main(String[] args){
try{
IOUtil.printHexByByteArray("E:\\Java\\JavaSE\\IO\\FileUtils.java");
}catch(IOException e){
e.printStackTrace();
}
}
}</span>

        运行结果:和实例代码1的结果一样。

        当字节数组不够大,一次性读不完文件时,怎么办呢?

        实例代码3:

<span style="font-size:18px;">import java.io.*;

public class IOUtil{
/*
* 读取指定文件内容,按照十六进制输出到控制台
* 并且每输出10个byte换行
* 单字节读取不适合大文件,大文件效率很低
*/
public static void printHex(String fileName) throws IOException{
//把文件作为字节流进行读操作
FileInputStream in = new FileInputStream(fileName);
int b ;
int i = 1;
while((b = in.read())!=-1){
if(b <= 0xf){
//单个数前面补0
System.out.print("0");
}
//将整型b转换为十六进制表示的字符串
System.out.print(Integer.toHexString(b)+" ");
if(i++%10==0){
System.out.println();
}
}
//关闭读写流
in.close();
}

public static void printHexByByteArray(String fileName) throws IOException{
FileInputStream in = new FileInputStream(fileName);
byte[] buf = new byte[8 * 1024];
int bytes = 0;
int j = 1;
while((bytes = in.read(buf,0,buf.length))!=-1){
for(int i = 0 ; i < bytes;i++){
//byte类型8位,int类型32位
//为了避免数据转换错误,通过&oxff将高24位清零
System.out.print(Integer.toHexString(buf[i] & 0xff)+" ");
if(j++%10==0){
System.out.println();
}
}
}
in.close();
}

public static void main(String[] args){
try{
IOUtil.printHexByByteArray("E:\\Java\\JavaSE\\IO\\FileUtils.java");
}catch(IOException e){
e.printStackTrace();
}
}
}</span>

        运行结果:

JavaSE入门学习43:文件传输基础之I/O流(二)