一文带你了解Java中IO流与Guava的使用

2022-11-25 10:09:16

目录GuavaIO分类常用的流示例Guava中的IO其他结束语GuavaIO日常系统交互中,文件的上传下载都是常见的,一般我们会通过jdk提供的IO操作库帮助我们实现。IO指的是数据相对当前操作程...

目录
Guava IO
分类
常用的流
示例
Guava中的IO
其他
结束语

Guava IO

日常系统交互中,文件的上传下载都是常见的,一般我们会通过jdk提供的IO操作库帮助我们实现。IO指的是数据相对当前操作程序的入与出,将数据通过 输出流从程序输出,或者通过输入流将数据(从文件、网络、数据等)写入到程序,这里的IO指的是基于流作为载体进行数据传输。如果把数据比作合理的水,河就是IO流,也是数据的载体。

Java为我们提供了非常多的操作IO的接口与类,帮助开发者实现不同源间的数据传输,比如硬盘文件、网络传输、应用调用间的数据交互与传递。今天我们来简单了解下Java中的流 以及在Guava工具包中,针对IO操作做了什么样的封装与设计。

分类

在java.io包中有非常多的IO相关接口,我们可以根据流的输出类型、处理对象以及功能将其分为以下几种类型:

按数据流向

输入流 (java.io.InputStream) 用于实现将数据读入到程序
输出流 (java.io.OutputStream) 用于实现将数据从程序写出

按操作单位android

字节流:以字节(byte)为单位进行数据的读、写 (其中针对文件也提供了按基础数据类型的读与写DataInpoutStream,也就是按照Java基础类型所占字节数来进行定量字节读取并合并)
字符流:以字符(char)为单位进行数据的读、写,此时需要注意字符编码

区分:

字节流一般以Stream结尾 字符流一般以Reader或Writer结尾

按操作方式

读 (java.io.Reader):主要针对字符流的读取操作
写 (java.io.Writer):主要针对字符流的写出操作

按功能

缓存流:按字节进行数据读写时,通过缓冲批量写入来提高传输效率
转换流:实现输入/出与读/写方式间的转换

常用的流

操作文件的

java.io.FileinputStream/FileOutputStream java.io.FileReader/FileWriter

通用的字节流

java.io.InputStreamReader/outputStreamWriter

缓冲流

java.io.BufferedReader/Bufferedwriter java.io.BufferedInputStream/BufferedOutputStream

数据流

java.io.DataInpoutStream/DataOutputStream

功能型的

java.io.PrintWriter/PrintStream

对象序列化相关的

java.io.ObjectInputStream/ObjectOutputStream

可见,提供的IO对象基本都是成对出现的,用以完成数据的输入输出,实现程序与外部载体间的数据交换

示例

下面我们通过一些常用示例来看看IO的使用的场景与使用方法:

文件复制
文件的合并
读取文件内容为字符串
字节数组转换成流
对象序列化与反序列化
流的转换
......

文件复制

@Test
publicvoidcopyByBytes()throwsIOException{
Stringroot=FileTests.class.getResource("/").getPath();

FileInputStreamfis=newFileInputStream(newFile(root,"/start.BAT"));
FileOutputStreamfos=newFileOutputStream(root+"/out2.bat");

byte[]buff=newbyte[100];

intb;
while((b=fis.read(buff))!=-1){
fos.write(buff,0,b);
}
//close
}

文件合并

@Test
publicvoidmergeFiles()throwsIOException{
Filefile1=newFile("E:\\_projects\\sucls\\blog\\my_study\\guava\\guava-io\\src\\test\\java\\com\\sucls\\blog\\guava\\io\\category\\FileTests.java");
Filefile2=newFile("E:\\_projects\\sucls\\blog\\my_study\\guava\\guava-io\\src\\test\\java\\com\\sucls\\blog\\guava\\io\\category\\StreamTests.java");

Enumeration<InputStream>ins=Collections.enumeration(Arrays.asList(
newFileInputStream(file1),
newFileInputStream(file2)
));

SequenceInputStreamsequenceInputStream=newSequenceInputStream(ins);

FileOutputStreamfos=newFileOutputStream(root+"/out4");

byte[]buff=newbyte[100];

intread;//真实读取到的字节数
while((read=sequenceInputStream.read(buff))!=-1){
fos.write(buff,0,read);
}

fos.close();
}

读取文件内容为字符串

@Test
publicvoidreadStringFromFile()throwsIOException{
FileReaderfileReader=newFileReader(newFile(this.getClass().getResource("/").getPath(),"/start.bat"));

StringBuilderstringBuilder=newStringBuilder();

inti;
while((i=fileReader.read())!=-1){
stringBuilder.append((char)i);//按字符读取
}

System.out.println(stringBuilder);//文件内容
}

字节数组转换成流

@Test
publicvoidbytesToStream(){
byte[]data=newbyte[1024];//来源于其他数据源

ByteArrayInputStreaminputStream=newByteArrayInputStream(data);

ByteArrayOutputStreamoutputStream=newByteArrayOutputStream();

intv;
while((v=inputStream.read())!=-1){
outputStream.write(v);
}

System.out.println(Arrays.toString(outputStream.toByteArray()));
}

对象序列化与反序列化

@Test
publicvoidobjectToFile()throwsIOException{

Personperson=newperson();
person.setName("张三").setAge(25);

Stringroot=FileTests.class.getResource("/").getPath();

FileOutputStreamfos=newFileOutputStream(newFile(root,"/person"));
ObjectOutputStreamoos=newObjectOutputStream(fos);

oos.writeObject(person);
}

@Test
publicvoidfileToObject()throwsIOException,ClassNotFoundException{
Stringroot=FileTests.class.getResource("/").getPath();

FileInputStreamfis=newFileInputStream(newFile(root,"/person"));
ObjectInputStreamois=newObjectInputStream(fis);

Personperson=(Person)ois.readObject();
System.out.println(person);
}

流的转换 将字节流转换成字符流来操作,同样以文件复制为例

@Test
publicvoidcopyByBuffer()throwsIOException{
Stringroot=FileTests.class.getResource("/").getPath();

FileInputStreamfis=newFileInputStream(newFile(root,"/start.bat"));
InputStreamReaderisr=newInputStreamReader(fis);
BufferedReaderbr=newBufferedReader(isr);

FileOutputStreamfos=newFileOutputStream(root+"/out3.bat");
OutputStreamWriterosw=newOutputStreamWriter(fos);
BufferedWriterbw=newBufferedWriter(osw);

Stringline;
while((line=br.readLine())!=null){
bw.append(line);
bw.newLine();
bw.flush();
}

//close
}

关于流的操作非常多,像包括网络通信中、音视频文件处理、流合并等等

Guava中的IO

关于IO的内容并不复杂,上面的那些例子在很多工具库中基本都会提供对应的API方便开发者调用,今天主要看下Guava IO模块针对流的操作提供了什么样的 封装

Files

提供对文件快捷读写方法 其中主要提供了ByteSource、ByteSink、CharSource、CharSink 4个类,分别对应按字节的读写与按字符的读写,

/**
*文件复制
*/
@Test
publicvoidcopy()throwsIOException{
Filefrom=newFile(root,"from");
Fileto=newFile(root,"to");
Files.copy(from,to);
}

/**
*文件移动
*/
@Test
publicvoidmove()throwsIOException{
Filefrom=newFile(root,"from");
Fileto=newFile(root,"to");
Files.move(from,to);
}

/**
*按行读取文件
*@throwsIOException
*/
@Test
publicvoidreadLines()throwsIOException{
Filedest=newFile(root,"start.bat");
List<String>lines=Files.readLines(dest,Charset.defaultCharset());
lines.forEach(System.out::println);
}

/**
*写入文件
*@throwsIOException
*/
@Test
publicvoidwriteToFile()throwsIOException{
Filedest=newFile(root,"demo.txt");
Files.write("helloworld!".getBytes(Charset.defaultCharset()),dest);
}

/**
*修改文件更新时间
*@throwsIOException
*/
@Test
publicvoidtouch()throwsIOException{
Filedest=newFile(root,"demo.txt");
Files.touch(dest);
}

/**
*文件的零拷贝
*@throwsIOException
*/
@Test
publicvoidmap()throwsIOException,URISyntaxException{
Filefrom=newFile(root,"from");
Fileto=newFile(root,"to");
Files.touchphp(to);

MappedByteBufferfromBuff=Files.map(from,MapMode.READ_ONLY,1024);
//=>
FileChannelchannel=FileChannel.open(Paths.get(to.toURI()),StandardOpenOption.WRITE);

channel.write(fromBuff);

channel.close();
}

/**
*读文件为字节数组
*@throwsIOException
*/
@Test
publicvoidfileAndBytes()throwsIOException{
Filedest=newFile(root,"start.bat");
ByteSourcebyteSource=Files.asByteSource(dest);
byte[]bytes=byteSource.read();
System.out.println(bytes);

//字节写入文件,实现复制
Filetarget=newFile(root,"start2.bat");
ByteSinkbyteSink=Files.asByteSink(target);
byteSink.write(bytes);
}

@Test
publicvoidwrapper(){
Filedest=newFile(root,"start.bat");
//作为字节读
Files.asByteSource(dest);
//作为字节写
Files.asByteSink(dest);

//作为字符读
Files.asCharSource(dest,Charset.defaultCharset());
//作为字符写
Files.asCharSink(dest,Charset.defaultCharset());
}

其他

管道流

PipedOutputStream  PipedInputStream 实现多线程间的数据通信;类似生产消费者模式

@Test
publicvoidpipe()throwsIOException{
PipedOutputStreampipedOutputStream=newPipedOutputStream();
PipedInputStreampipedInputStream=newPipedInputStream();
pipedOutputStream.connect(pipedInputStream);

newThread(()->{
while(true){
Stringdate=newDate().toString();
try{
pipedOutputStream.write(date.getBytes(StandardCharsets.UTF_8));
pipedOutputStream.flush();
TimeUnit.SECONDS.sleep(2);
}catch(IOExceptione){
thrownewRuntimeException(e);
}catch(InterruptedExceptione){
thrownewRuntimeException(e);
}
}
}).start();

newThread(()->{
while(true){
byte[]buff=newbyte[1024];
try{
intread=pipedInputStream.read(buff);
TimeUnit.SECONDS.sleep(4);
}catch(IOExceptione){
thrownewRuntimeException(e);
}catch(InterruptedExceptione){
thrownewRuntimeException(e);
}
System.out.println(newString(buff));
}
}).start();
}

结束语

在任何编程语言中,数据的IO都是比较常见并相当重要的。Guava作为工具型类库,主要是帮助开发者封装常用、重复的操作,开放出简介的API,不仅能让让代码更加整洁, 同时对开发出稳健程序也是比不可少的。

到此这篇关于一文带你了解Java中IO流与Guava的使用的文章就介绍到这了,更多相关Java IO流 Guava内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!