为什么我的"中"没有出现乱码?而能读出来?

来源:3-1 RandomAccessFile基本操作

蔚然成麟er

2017-03-15 22:44

package com.imooc;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Arrays;
import java.util.Random;
public class RafDemo {
 public static void main(String[] args) throws IOException{
  // TODO Auto-generated method stub
  File demo = new File("demo");//如果没有写绝对路径的话他就是一个相对路径目录就是在我们的项目下
  if(!demo.exists()){
   demo.mkdir();
  }
  File file = new File(demo,"Raf.dat");//以demo作为父目录后面跟一个文件
  if(!file.exists()){
   file.createNewFile();
  }
  RandomAccessFile raf = new RandomAccessFile(file,"rw");
  System.out.println("文件中没有写任何数据时指针的位置" + raf.getFilePointer());//得到指针的位置
  
  raf.write('A');//只写了一个字节一个char是两个字节所以他会把'A'的后八位写进去,也有可能后八位已经能表示这个'A'前面的高八位可能是00000000
  System.out.println("写完一个字节之后指针的位置" + raf.getFilePointer());
  raf.write('B');
  System.out.println("写完第二个字节之后指针的位置" + raf.getFilePointer());
  
  int i = 0X7fffffff;//Java最大的整数
//  用write()每次只能写一个字节如果要把i写进去就得写四次
  raf.write(i >>> 24);//高八位
  raf.write(i >>> 16);//第二个高八位
  raf.write(i >>> 8);//第三个高八位
  raf.write(i);//只写后八位自动写最低的八位
  System.out.println("写完一个int类型的数据之后指针的位置" + raf.getFilePointer());
  
//  可以直接写一个int因为RandomAccessFile提供了writeInt()
  raf.writeInt(i);//writeInt()的底层就是做了上述四个write()
  System.out.println("再次写完一个int类型的数据之后指针的位置" + raf.getFilePointer());
  /*writeInt()的底层源码
  public final void writeInt(int v) throws IOException {
        write((v >>> 24) & 0xFF);//0xFF的作用把前面的0去掉因为右移之后前面都补0了
        write((v >>> 16) & 0xFF);
        write((v >>>  8) & 0xFF);
        write((v >>>  0) & 0xFF);
        //written += 4;
        }
        
         与上述的四行write()比较
         raf.write(i >>> 24);把i右移24位只写后八位前面的0都不写了
   */
  String s = "中";//中文占两个字节
  byte[] gbk = s.getBytes("gbk");
  raf.write(gbk);//直接写一个字节数组
  System.out.println("写完一个Stirng类型的中文字符的数据之后指针的位置" + raf.getFilePointer());
  
  System.out.println("从头到尾写入到文件中的字节的总长度 " + raf.length());//文件的长度
  
//  读文件必须把指针移到文件头部
  raf.seek(0);//指针移到文件的开始
  
  //一次性读取,把文件中的内容都读到字节数组中
  byte[] buf = new byte[(int)raf.length()];
  
//  raf.read();//只能读一个字节
  raf.read(buf);//能够把文件中的内容读到字节数组里面
  System.out.println(Arrays.toString(buf));//读取之后把字节数组输出
  /*
   * 从输出结果中看[65, 66, 127, -1, -1, -1, 127, -1, -1, -1, -42, -48]65,66也就是A和B了原因即使他的后八位已经能表示了
   */
  
  /**
   * 把整个字节数组构造成字符串
   */
  String s1 = new String(buf,"gbk");
  System.out.println(s1);
  /*
   * 从输出结果来看AB??????中
   * 因为整个自己数组和我们想的是不一样的最后一个String类型的中文字符"中"在Java的字符串中是utf-16be的编码
   * 即使在写入的时候转换成了gbk但是在重新构成的时候前后还有其他字节你在写的时候是一个字节数组除非你单独包装写入中文字符"中"的情况因为前面还有字节
   * 除非你只读两个字节把他包装
   * 正好定位到它的位置读两个字节包装起来就正好是一个中文反则就会有乱码
   */
  /**
   * 以16进制输出
   */
  for (byte b : buf) {
   System.out.print(Integer.toHexString(b & 0xff) + " ");
  }
//  关闭文件
  raf.close();
  
  /**
   * 以上的read()方法不是读一个字节是一下全部读取其实也可以一次读一个字节
   * 或者定位到某个位置比如定位到第10个位置读两个字节就读到了一个中文用gbk转化就正好是一个字符串
   */
 }
}
输出结果
文件中没有写任何数据时指针的位置0

写完一个字节之后指针的位置1

写完第二个字节之后指针的位置2

写完一个int类型的数据之后指针的位置6

再次写完一个int类型的数据之后指针的位置10

写完一个Stirng类型的中文字符的数据之后指针的位置12

从头到尾写入到文件中的字节的总长度 12

[65, 66, 127, -1, -1, -1, 127, -1, -1, -1, -42, -48]

AB??????中

41 42 7f ff ff ff 7f ff ff ff d6 d0
写回答 关注

2回答

  • qwertyuioplkjh
    2017-10-19 09:21:17

    那为什么中间会出现乱码,怎么样能显示中间的int

  • 洗头最爱用飘柔
    2017-03-16 15:13:58

    因为被系统识别了编码方式,同时正确解码了。你可以把51行的换成byte[] gbk = s.getBytes("utf-8");在不更改74行的gbk解码方式下,就会出现乱码,如果也改成了utf-8就会成功解码。

文件传输基础——Java IO流

为您介绍IO流的使用,以及对象的序列化和反序列化的内容

133754 学习 · 1030 问题

查看课程

相似问题