IO深入操作
1:字符编码
背景:
在计算机的世界里面只认识0,1的数据,如果想要描述一些文字的编码就需要对这些二进制的数据进行组合,所以才有了现在可以看见的中文,但是在进行编码的时候如果要想正确显示出内容一定需要有解码,所以编码和解码坑定要采用统一的标准。
2列出本机属性
public class Test {
public static void main(String[] args) throws Exception {
System.getProperties().list(System.out);
}
}//输出结果
-- listing properties --
sun.desktop=windows
awt.toolkit=sun.awt.windows.WToolkit
java.specification.version=9
file.encoding.pkg=sun.io
sun.cpu.isalist=amd64
**sun.jnu.encoding=GBK**
java.class.path=D:\Eclipse\eclipse\D\eclipse-workspac...
java.vm.vendor=Oracle Corporation
sun.arch.data.model=64
user.variant=
java.vendor.url=http://java.oracle.com/
user.timezone=
os.name=Windows 10
java.vm.specification.version=9
sun.java.launcher=SUN_STANDARD
user.country=CN
sun.boot.library.path=C:\Program Files\Java\jdk-9.0.1\bin
sun.java.command=开始面试.Test a b
jdk.debug=release
sun.cpu.endian=little
user.home=C:\Users\sc
user.language=zh
java.specification.vendor=Oracle Corporation
java.home=C:\Program Files\Java\jdk-9.0.1
file.separator=\
java.vm.compressedOopsMode=32-bit
line.separator=
java.vm.specification.vendor=Oracle Corporation
java.specification.name=Java Platform API Specification
java.awt.graphicsenv=sun.awt.Win32GraphicsEnvironment
user.script=
sun.management.compiler=HotSpot 64-Bit Tiered Compilers
java.runtime.version=9.0.1+11
user.name=sc
path.separator=;
os.version=10.0
java.runtime.name=Java(TM) SE Runtime Environment
file.encoding=GBK
java.vm.name=Java HotSpot(TM) 64-Bit Server VM
java.vendor.url.bug=http://bugreport.java.com/bugreport/
java.io.tmpdir=C:\Users\sc\AppData\Local\Temp\
java.version=9.0.1
user.dir=D:\Eclipse\eclipse\D\eclipse-workspac...
os.arch=amd64
java.vm.specification.name=Java Virtual Machine Specification
java.awt.printerjob=sun.awt.windows.WPrinterJob
sun.os.patch.level=
java.library.path=C:\Program Files\Java\jdk-9.0.1\bin;C...
java.vm.info=mixed mode
java.vendor=Oracle Corporation
java.vm.version=9.0.1+11
sun.io.unicode.encoding=UnicodeLittle
java.class.version=53.0
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Test {
public static void main(String[] args) throws Exception {
OutputStream output = new FileOutputStream("D:" + File.separator + "mldn.txt");
output.write("头条真的好难进去".getBytes());
output.close();
}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class Test {
public static void main(String[] args) throws Exception {
OutputStream output = new FileOutputStream("D:" + File.separator + "mldn.txt");
output.write("头条,等我!".getBytes("ISO8859-1"));
output.close();
}
}
2:内存操作流
在之前使用的全部都是文件操作流,文件操作流的特点,程序利用InoutStream读取文件内容,而后程序利用OutputStream向文件输出内容,所有的操作都是以文件为终端的。
在Java里面提供有两类的内存操作流:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "www.mldn.cn" ; // 小写字母
InputStream input = new ByteArrayInputStream(str.getBytes()) ; // 将数据保存在内存流
OutputStream output = new ByteArrayOutputStream() ; // 读取内存中的数据
int data = 0 ;
while ((data = input.read()) != -1) { // 每次读取一个字节
output.write(Character.toUpperCase(data)); // 保存数据
}
System.out.println(output);
input.close();
output.close();
}
}
如果现在不希望只是以字符串的形式返回,因为可能存放的是其他的二进制数据,那么此时就可以利用
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
String str = "www.mldn.cn" ; // 小写字母
InputStream input = new ByteArrayInputStream(str.getBytes()) ; // 将数据保存在内存流
// 必须使用子类来调用子类自己的扩展方法
ByteArrayOutputStream output = new ByteArrayOutputStream() ; // 读取内存中的数据
int data = 0 ;
while ((data = input.read()) != -1) { // 每次读取一个字节
output.write(Character.toUpperCase(data)); // 保存数据
}
byte result [] = output.toByteArray() ; // 获取全部数据
System.out.println(new String(result)); // 自己处理字节数据
input.close();
output.close();
}
}
在最初的时候可以利用ByteArrayOutputStream实现大规模文本文件的读取。
3:管道流
范例:实现管道操作;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class Test {
public static void main(String[] args) throws Exception {
SendThread send = new SendThread();
ReceiveThread receive = new ReceiveThread();
send.getOutput().connect(receive.getInput()); // 进行管道连接
new Thread(send, "消息发送线程").start();
new Thread(receive, "消息接收线程").start();
}
}
class SendThread implements Runnable {
private PipedOutputStream output; // 管道的输出流
public SendThread() {
this.output = new PipedOutputStream(); // 实例化管道输出流
}
@Override
public void run() {
for (int x = 0; x < 10; x++) {
try { // 利用管道实现数据的发送处理
this.output.write(
("【第" + (x + 1) + "次信息发送 - " + Thread.currentThread().getName() + "】www.mldn.cn\n").getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
this.output.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public PipedOutputStream getOutput() {
return output;
}
}
class ReceiveThread implements Runnable {
private PipedInputStream input;
public ReceiveThread() {
this.input = new PipedInputStream();
}
@Override
public void run() {
byte data[] = new byte[1024];
int len = 0 ;
ByteArrayOutputStream bos = new ByteArrayOutputStream() ;// 所有的数据保存到内存输出流
try {
while((len = this.input.read(data)) != -1) {
bos.write(data,0,len); // 所有的数据保存到内存流
}
System.out.println("{" + Thread.currentThread().getName() + "接收消息}\n" + new String(bos.toByteArray()));
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
this.input.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public PipedInputStream getInput() {
return input;
}
}
//运行结果
{消息接收线程接收消息}
【第1次信息发送 - 消息发送线程】www.mldn.cn
【第2次信息发送 - 消息发送线程】www.mldn.cn
【第3次信息发送 - 消息发送线程】www.mldn.cn
【第4次信息发送 - 消息发送线程】www.mldn.cn
【第5次信息发送 - 消息发送线程】www.mldn.cn
【第6次信息发送 - 消息发送线程】www.mldn.cn
【第7次信息发送 - 消息发送线程】www.mldn.cn
【第8次信息发送 - 消息发送线程】www.mldn.cn
【第9次信息发送 - 消息发送线程】www.mldn.cn
【第10次信息发送 - 消息发送线程】www.mldn.cn
管道就类似于医院打点滴效果,一个负责发送,一个负责接收,中间靠一个管道连接。
4:RandomAccessFile
对于文件内容的处理操作主要是通过InputStream(Reader),OutputStream(Writer)来实现,但是利用这些类实现的内容读取能够将数据部分读取进来,如果说现在有一个这样的要求:
import java.io.File;
import java.io.RandomAccessFile;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("d:" + File.separator + "mldn.txt"); // 定义操作文件
RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 读写模式
String names[] = new String[] { "zhangsan", "wangwu ", "lisi " };
int ages[] = new int[] { 30, 20, 16 };
for (int x = 0; x < names.length; x++) {
raf.write(names[x].getBytes()); // 写入字符串
raf.writeInt(ages[x]);
}
raf.close();
}
}
import java.io.File;
import java.io.RandomAccessFile;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
File file = new File("d:" + File.separator + "mldn.txt"); // 定义操作文件
RandomAccessFile raf = new RandomAccessFile(file, "rw"); // 读写模式
{ // 读取“李四”的数据,跳过24位
raf.skipBytes(24) ;
byte[] data = new byte[8];
int len = raf.read(data) ;
System.out.println("姓名:" + new String(data,0,len).trim() + "、年龄:" + raf.readInt());
}
{ // 读取“王五”的数据,回跳12位
raf.seek(12);
byte[] data = new byte[8];
int len = raf.read(data) ;
System.out.println("姓名:" + new String(data,0,len).trim() + "、年龄:" + raf.readInt());
}
{ // 读取“张三”的数据,回跳头
raf.seek(0); // 回到顶点
byte[] data = new byte[8];
int len = raf.read(data) ;
System.out.println("姓名:" + new String(data,0,len).trim() + "、年龄:" + raf.readInt());
}
raf.close();
}
}
整体的使用之中由用户自行定义要读取的位置,而后按照指定的结构进行数据的读取。