字符编码

常见编码:

  • GBK/GB2312国标,GB2312只包含简体中文,GBK有简体中文和繁体中文
  • ISO8859-1,国际通用编码,可以描述所有字母信息,如果是象形文字需要经过编码处理。
  • UNCODE,十六进制存储,可以描述所有文字信息
  • UTF编码,象形文字采用十六进制编码,而其他文字采用ISO8859-1编码,适合用于快速传输,节约带宽。也就成为了开发首选编码。主要使用UTF-8编码

要想知道系统中支持的代码规则,则需要通过程序列出全部 属性:
列出本机属性:

package wzr.study09.io;

public class PropertyTest {

	public static void main(String[] args) {
		System.getProperties().list(System.out);
	}

}

强制性设置编码:

import java.io.OutputStream;
import java.io.*;

public class SetcodeTest {
	public static void main(String args[]) throws Exception {
		File file=new File("F:\\course\\file.txt");
		OutputStream out=new FileOutputStream(file,true);
		out.write("\r\n强制设置编码问题\r\n".getBytes("GBK"));
		out.close();
	}
}

强制设置代码和资源都为UTF-8是最好的解决方式。

内存操作流

想要使用IO操作但又不想产生文件,此时解决办法为,以内存(临时文件)为终端。

java设置请求数据编码 java io设置编码_java设置请求数据编码


使用内存需要调用的IO流与使用文件需要调用的IO流相反字节内存操作流:ByteArrayOutputStream,ByteArrayInputStream

字符内存操作流:CharArrayWriter,CharArrayReader

java设置请求数据编码 java io设置编码_管道流_02

java设置请求数据编码 java io设置编码_管道流_03

java设置请求数据编码 java io设置编码_java设置请求数据编码_04


java设置请求数据编码 java io设置编码_java设置请求数据编码_05


首先分析ByteArrayInputStream,ByteArraOutputStream构造方法:

  • ByteArrayInputStream构造(将数据放到内存,然后取出):public ByteArrayInputStream(byte[] buf)
  • ByteArrayOutputStream构造(是个无参构造):public ByteArrayOutputStream()
  • ByteArrayOutputStream中有将内存流中全部的数据信息读取出来。
  • 获取数据:public byte[] toByteArray()
  • 使用字符串的形式获取:public String toString()

范例:使用内存流实现小写字母转大写字母的操作

import java.io.*;

public class MemoryIOTest {

	public static void main(String[] args) throws Exception {
		String str="abcdefg";
		InputStream in=new ByteArrayInputStream(str.getBytes());
		OutputStream out=new ByteArrayOutputStream();
		int data=0;
		while((data=in.read())!=-1) {
			out.write(Character.toUpperCase(data));
		}
		System.out.println(out);
		in.close();
		out.close();
		
	}

}

如果不希望以字符串的形式返回,可以使用OutputStream子类ByteArrayOutputStream的扩展功能获取全部字节数据

import java.io.*;

public class MemoryIOTest {

	public static void main(String[] args) throws Exception {
		String str="abcdefg";
		InputStream in=new ByteArrayInputStream(str.getBytes());
		//必须子类自己使用自己的扩展功能
		ByteArrayOutputStream out=new ByteArrayOutputStream();
		int data=0;
		while((data=in.read())!=-1) {
			out.write(Character.toUpperCase(data));
		}
		byte bt[]=out.toByteArray();
		System.out.println(new String(bt));
		in.close();
		out.close();
		
	}

}

管道流

实现两个线程之间IO处理,管道流也分为字节流和字符流两类。

java设置请求数据编码 java io设置编码_管道流_06


字节管道流:PipiedOutputStream,PipedInputStream

字符管道流:PipedWriter,PipedReader

连接:

OutputStream:public void connect(PipedInputStream snk) throws IOException Writer:public void connect(PipedReader snk) throws IOException

范例实现管道操作:

package wzr.study09.io;

import java.io.*;

public class PipelineTest {

	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 out;
	public SendThread() {
		out=new PipedOutputStream();
	}
	@Override
	public void run() {
		for(int i=0;i<10;i++) {
			try {
				out.write((Thread.currentThread().getName()+"的第"+(i+1)+"次发送!\n").getBytes());
				Thread.sleep(1000);//那么依次交叉实现是线程的内容。
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		//为什么要关闭?关闭了Thread就不能再次执行了
		try {
			out.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	public PipedOutputStream getOutput() {
		return out;
	}
}
class ReceiveThread implements Runnable{
	private PipedInputStream in;
	public ReceiveThread() {
		in=new PipedInputStream();
	}
	@Override
	public void run() {
		byte bt[]=new byte[1024];
		int len=0,num=1;
		ByteArrayOutputStream bos=new ByteArrayOutputStream();
		try {
			//适用于收一个输出一个
			while((len=in.read(bt))!=-1) {
				System.out.println(Thread.currentThread().getName()+"第"+ num++ +"接收:\n"+new String(bt,0,len));
			}
//			一次性全部输出
//			while((len=in.read(bt))!=-1) {
//				bos.write(bt,0,len);
//			}
//			System.out.println(Thread.currentThread().getName()+"第"+ num++ +"接收:\n"+new String(bos.toByteArray()));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			in.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	public PipedInputStream getInput() {
		return in;
	}
}

RandomAccessFile随机存储类

对于20G的大文件,InputStream(Reader),OutputStream(Writer)很难有效实现。
RandomAccessFile可以,其可以实现文件的跳跃式读取,可以读取中间的部分内容(前提:需要有一个完善的保存形式,数据保存的位数要都确定好)。
构造方法:public RandomAccessFile(File file,String mode) throws FileNotFoundException

  • 文件处理形式:r只读,rw读写

RandomAccessFile数据读取上可以跳字节读取:

  • 向下跳:public int skipBytes(int n) throws IOException向后跳n个字节
  • 自由跳:public void seek(long pos) throws IOException跳向pos的位置
    范例:读取数据
package wzr.study09.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileTest {

	public static void main(String[] args) throws Exception {
		File file=new File("F:\\course\\random.txt");
		if(!file.exists()) {
			file.createNewFile();
		}
		RandomAccessFile raf=new RandomAccessFile(file,"rw");
		String str[]=new String[] {"zhangsan","lisi    ","wangwu  "};
		int ages[]=new int[] {18,25,21};
		for(int i=0;i<str.length;i++) {
			raf.write(str[i].getBytes());
			raf.writeInt(ages[i]);
		}
		raf.close();
	}

}

RandomAccessFile类主要作用是文件读取上。数据 长度固定,所以可以进行跳字节读取。
范例:读取数据

package wzr.study09.io;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileTest {

	public static void main(String[] args) throws Exception {
		File file=new File("F:\\course\\random.txt");
		RandomAccessFile raf=new RandomAccessFile(file,"rw");
		{//读取王五
			raf.skipBytes(24);
			byte bt[]=new byte[8];
			int len=raf.read(bt);
			System.out.println("名字:"+new String(bt,0,len)+",年龄:"+raf.readInt());
		}
		{//读取lisi
			raf.seek(12);
			byte bt[]=new byte[8];
			int len=raf.read(bt);
			System.out.println("名字:"+new String(bt,0,len)+",年龄:"+raf.readInt());
		}
		{//读取zhangsan
			raf.seek(0);
			byte bt[]=new byte[8];
			int len=raf.read(bt);
			System.out.println("名字:"+new String(bt,0,len)+",年龄:"+raf.readInt());
		}
		raf.close();
	}

}

由用户自行定义读取的位置。