Java I/O

更多参考《Java in a nutshell》

~~

 java.nio.charset 字符集包,CharsetEncoderCharsetDecoder允许对编码和解码过程进行精细的控制

String input = "你123好";
Charset charset = Charset.forName("ISO-8859-1");
CharsetEncoder encoder = charset.newEncoder();
encoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
CharsetDecoder decoder = charset.newDecoder();
CharBuffer buffer = CharBuffer.allocate(32);
buffer.put(input);
buffer.flip();
try {
    ByteBuffer byteBuffer = encoder.encode(buffer);
    CharBuffer cbuf = decoder.decode(byteBuffer);
    System.out.println(cbuf);  //输出123
} catch (CharacterCodingException e) {
    e.printStackTrace();
}  
 

 

 

 

Channel之间transfer数据

    public static String readFile(File file) throws IOException {
        FileInputStream fis = new FileInputStream(file);
        FileChannel channel = fis.getChannel();
        ByteArrayOutputStream os = new ByteArrayOutputStream(0x10000);
        WritableByteChannel wchannel = Channels.newChannel(os);
        channel.transferTo(0, file.length(), wchannel);
        channel.close();
        wchannel.close();
        return os.toString();
   }

    public static void writeFile(File file, final String content) throws IOException {
        if (!file.exists())
            file.createNewFile();
        
        FileOutputStream fos = new FileOutputStream(file);
        FileChannel channel = fos.getChannel();
        ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes());
        ReadableByteChannel rchannel = Channels.newChannel(is);
        channel.transferFrom(rchannel, 0, content.getBytes().length);

        channel.close();
        rchannel.close();
   }

 

 

NIO  ByteBuffer

将数据读入缓冲区之前,需要调用clear方法;将缓冲区中的数据输出之前,需要调用flip方法。

ByteBuffer buffer = ByteBuffer.allocate(32);
CharBuffer charBuffer = buffer.asCharBuffer();
String content = charBuffer.put("Hello ").put("World").flip().toString();
System.out.println(content);  

 

 

将Stream转换成byte[]

private byte[] saveStream(InputStream input) throws IOException {
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    ReadableByteChannel readChannel = Channels.newChannel(input);
    ByteArrayOutputStream output = new ByteArrayOutputStream(32 * 1024);
    WritableByteChannel writeChannel = Channels.newChannel(output);
    while ((readChannel.read(buffer)) > 0 || buffer.position() != 0) {
        buffer.flip();
        writeChannel.write(buffer);
        buffer.compact();
    }
    return output.toByteArray();

 

 

如果一个流支持标记的话(通过markSupported方法判断),就可以在流开始的地方通过mark方法添加一个标记,当完成一次对流的使用之后,通过reset方法就可以把流的读取位置重置到上次标记的位置,即流开始的地方。如此反复,就可以复用这个输入流。大部分输入流的实现是不支持标记的。可以通过BufferedInputStream进行包装来支持标记。

private InputStream prepareStream(InputStream ins) {
    BufferedInputStream buffered = new BufferedInputStream(ins);
    buffered.mark(Integer.MAX_VALUE);
    return buffered;
}

private void resetStream(InputStream ins) throws IOException {
    ins.reset();
    ins.mark(Integer.MAX_VALUE);

 

 

Interrupt a thread while doing block I/O operation:
try {
new InputStreamReader(
Channels.newInputStream(
(new FileInputStream(FileDescriptor.in)).getChannel())));
catch (…) {
}
以特定字符编码从文件中读取一行:

File file = new File("test");
FileInputStream is = new FileInputStream(file);
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "gbk"));
String str;
while((str = reader.readLine()) != null) {
System.out.println(str);
}
BufferedInputStream:

File file = new File("moandroid.txt");
InputStream is = new BufferedInputStream(new FileInputStream(file));
long length = file.length();
if(length>Integer.MAX_VALUE)
{
System.out.println(“source file is too large”);
return ;
}
byte[] bytes = new byte[(int)length];
int offset = 0,numRead = 0;
while( offset<bytes.length && (numRead = is.read(bytes,offset,bytes.length-offset))>= 0)
offset += numRead;
if(offset<bytes.length)
throw new IOException(“Could not completely read file”+file.getName());
is.close();

DataInputStream:

File file = new File("moandroid.txt");
is = new DataInputStream(new FileInputStream(file));
int intData = is.readInt();
boolean boolData = is.readBoolean();


end