java文件读取内容转码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java文件读取内容转码相关的知识,希望对你有一定的参考价值。

public static void main(String[] args) throws IOException
// TODO Auto-generated method stub
File file=new File("F://svn//Test.properties");
InputStream io=new FileInputStream(file);
byte[] buf=new byte[(int)file.length()];
io.read(buf);
String str=new String(buf);
byte[] str1=str.getBytes();
//String str="\u8fd9\u662f\u4e00\u4e2a\u5bc6\u7801";
System.out.println(str.length());
System.out.println("file.encoding:" + System.getProperty("file.encoding"));
String st=transaction(str1);
System.out.println(st);

protected static String transaction(byte[] filename)
String str=null;
try
str=new String(filename,"UTF-8");
catch (UnsupportedEncodingException e)
// TODO Auto-generated catch block
e.printStackTrace();

return str;

就这样一个代码,为什么从文件中读取得到的String,查看length得到的是36,转码得不到预期结果。
//String str="\u8fd9\u662f\u4e00\u4e2a\u5bc6\u7801";

而直接写在代码里面的String,length是6,转码成功为“这是一个密码”

读取的文件流如果是read(读取字节流的时候,中文就会是乱码)方法,所以现在全都是听过readline方式进行的读取。举例:
可以通过BufferedReader 流的形式进行流缓存,之后通过readLine方法获取到缓存的内容。
BufferedReader bre = null;
try
String file = "D:/test/test.txt";
bre = new BufferedReader(new FileReader(file));//此时获取到的bre就是整个文件的缓存流
while ((str = bre.readLine())!= null) // 判断最后一行不存在,为空结束循环

System.out.println(str);//原样输出读到的内容

bre.close(),//关闭流,否则bre流会一直存在,直到程序运行结束。

除此之外,java文件读取的时候有中文就很出现乱码,通常获取到的文件中通常都是“iso8859-1”格式,需要转换为“UTF-8”格式。
如:String str = new String(str.getByte("iso8859-1"),"UTF-8");进行下强制转换后在进行读取即可。
备注:通常格式有GBK、UTf-8、iso8859-1、GB2312,如果上面的强制转换不成功,依次进行这些格式的尝试,肯定是可以解决问题的。
参考技术A 打散重装就好了。
/**
* 编码:输入一个字符串,返回编码后的字符串
*
* @author qinzy
* @param str
* @return
*/
public static String encode(String str)
if (str == null || "".equals(str))
return str;
try
str = URLEncoder.encode(str, "UTF-8");
catch (UnsupportedEncodingException e1)
e1.printStackTrace();

return str;

/**
* 编码:输入一个字符串,返回两次编码后的字符串
*
* @author qinzy
* @param str
* @return
*/
public static String encode2(String str)
if (str == null || "".equals(str))
return str;
try
str = URLEncoder.encode(URLEncoder.encode(str, "UTF-8"), "UTF-8");
catch (UnsupportedEncodingException e1)
e1.printStackTrace();

return str;

/**
* 解码:输入一个字符串,返回解码后的字符串
*
* @author qinzy
* @param str
* @return
*/
public static String decode(String str)
if (str == null || "".equals(str))
return str;
try
str = URLDecoder.decode(str, "UTF-8");
catch (UnsupportedEncodingException e1)
e1.printStackTrace();

return str;
追问

打散重装?是将一个字的截取出来再重新组成一个新的字符串?

追答

我给你的这3个方法你看了么 前两个方法就是打散重装,就是将一个字符串打散成2进制编码,再重新组装成自己想要的编码格式。这样能防止乱码的产生。

追问

用第一个方法得到
%5Cu8fd9%5Cu662f%5Cu4e00%5Cu4e2a%5Cu5bc6%5Cu7801

用第二个方法得到
%255Cu8fd9%255Cu662f%255Cu4e00%255Cu4e2a%255Cu5bc6%255Cu7801

用第三个方法得到
\u8fd9\u662f\u4e00\u4e2a\u5bc6\u7801

即使在第一个方法后用第三个方法也得到\u8fd9\u662f\u4e00\u4e2a\u5bc6\u7801
却不是想要的:这是一个密码

追答

在java中汉字在后台是以16进制存储的,你这个是16进制的代码。你只要直接输出
String a = "\u8fd9";
System.out.println(a);
就能输出汉字“这”了。写到文件里也是这样。

本回答被提问者和网友采纳
参考技术B 有图吗?把你的代码拿出来看看

Python基础3 文件操作字符编码与转码

文件操作

对文件操作过程

打开文件,得到文件句柄赋值给变量
操作
关闭文件

打开文件的模式有:

r,只读模式(默认)。

w,只写模式。【不可读;不存在则创建;存在则删除内容;】

a,追加模式。【可读;   不存在则创建;存在则只追加内容;】

"+" 表示可以同时读写某个文件

r+,可读写文件。【可读;可写;可追加】

w+,写读

a+,同a

"U"表示在读取时,可以将 \r \n \r\n自动转换成 \n (与 r 或 r+ 模式同使用)

rU

r+U

"b"表示处理二进制文件(如:FTP发送上传ISO镜像文件,linux可忽略,windows处理二进制文件时需标注)

rb

wb

ab

#文件句柄
f = open(yesterday,r,encoding=utf-8)
 
#r模式为读模式
f = open(yesterday,r,encoding=utf-8)
 
#w模式为写,创建文件
f = open(yesterday2,w,encoding=utf-8)
f.write("我爱北京天安门,\n")
f.write("天安门上太阳升\n")
 
#a模式为追加,创建文件
f = open(yesterday2,a,encoding=utf-8)
f.write("我爱北京天安门,\n")
f.write("天安门上太阳升\")
 
#关闭文件
f.close()

#读前5行
f = open(yesterday2,r,encoding=utf-8)
for i in range(5):
    print (f.readline())

# 循环读每行
f = open(yesterday2,r,encoding=utf-8)
for i in f.readlines():
    print (i,)

# 读前9行
count = 0
f = open(yesterday2,r,encoding=utf-8)
for line in f:
    if count == 9:
        print (------我是分割线-------)
        count += 1
        continue
    print (line.strip())
    count += 1

#seek和tall用法
f = open(yesterday2,r,encoding=utf-8)
print (f.tell())
print (f.readline().strip())
print (f.readline().strip())
print (f.readline().strip())
print (f.tell())
f.seek(0)
print (f.readline().strip())

#强制刷新保存
f.flush()

#截断
f = open(yesterday2,r,encoding=utf-8)
f.truncate(10)

#读写,r+,读和追加
f = open(yesterday2,r+,encoding=utf-8)
print (f.readline())
print (f.readline())
print (f.readline())
f.write(-----diao----\n)
print (f.readline())

#写读,w+,先创建一个文件
f = open(yesterday2,w+,encoding=utf-8)
f.write(-----diao----\n)
f.write(-----diao----\n)
f.write(-----diao----\n)
f.write(-----diao----\n)
print (f.tell())
f.seek(10)
print (f.readline())
f.write(should\n)
 
#追加读,a+

#读二进制文件
f = open(yesterday2,rb)
print (f.readline())

#写二进制文件
f = open(yesterday2,wb)
f.write(hello\n.encode(utf-8))
f.close()

#文件修改
f = open(yesterday2,r,encoding=utf-8)
f_new = open(yesterday3,w,encoding=utf-8)
for line in f:
    if 肆意的快乐 in line:
        line = line.replace(肆意的快乐等我享受,肆意的快乐等xxx享受)
    f_new.write(line)
f.close()

with语句

with open(file_name, r) as f:
    ...

# 在Python 2.7 后,with又支持同时对多个文件的上下文进行管理
with open(log1) as obj1, open(log2) as obj2:
    ...

字符编码与转码

需知:

在python2默认编码是ASCII, python3里默认是unicode

unicode 分为 utf-32(占4个字节),utf-16(占两个字节),utf-8(占1-4个字节), so utf-16就是现在最常用的unicode版本, 不过在文件里存的还是utf-8,因为utf8省空间

在py3中encode,在转码的同时还会把string 变成bytes类型,decode在解码的同时还会把bytes变回string

python2

#-*-coding:utf-8-*-

import sys
print(sys.getdefaultencoding())


msg = "我爱北京天安门"
msg_gb2312 = msg.decode("utf-8").encode("gb2312")
gb2312_to_gbk = msg_gb2312.decode("gbk").encode("gbk")

print(msg)
print(msg_gb2312)
print(gb2312_to_gbk)

python3

#-*-coding:gb2312 -*-   #这个也可以去掉


import sys
print(sys.getdefaultencoding())


msg = "我爱北京天安门"
#msg_gb2312 = msg.decode("utf-8").encode("gb2312")
msg_gb2312 = msg.encode("gb2312") #默认就是unicode,不用再decode,喜大普奔
gb2312_to_unicode = msg_gb2312.decode("gb2312")
gb2312_to_utf8 = msg_gb2312.decode("gb2312").encode("utf-8")

print(msg)
print(msg_gb2312)
print(gb2312_to_unicode)
print(gb2312_to_utf8)

赋值及深浅拷贝

对于 数字 和 字符串 而言,赋值、浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址

赋值

#赋值
#n1 n2指向同一内存地址,修改n1后n2依然指向之前的内存地址,n1内存地址变了
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
n2 = n1
print(id(n1))
print(id(n2))
n1 = {"k1": "wu", "k2": 123, "k3": ["alex", 456]}
print(id(n1))
print(id(n2))
print(n2)

浅拷贝

#复制列表,浅copy
#增加一个内存指针指向已经存在的内存,只影响第一层
names = [ZhangYang,ZhaoYi,ShaoYiFan,JiaChen,MengLingJun,LiuLin,[YangRui]]
names2  = names.copy()
print (names,names2)

import copy
#浅copy,3中方式
person = [name,[saving,100]]
‘‘‘
p1 = copy.copy(person)
p2 = person[:]
p3 = list(person)
‘‘‘
p1 = person[:]
p2 = person[:]
p1[0] = tom
p2[0] = jane
p1[1][1] = 50
print (p1)
print (p2)

深拷贝

import copy
#复制列表,深copy
#增加一个内存指针并申请一块新的内存
 
names2 = copy.deepcopy(names)
 
names[3] = 汤姆
names[-1][0] = 杰克
print (names)
print (names2)
 

以上是关于java文件读取内容转码的主要内容,如果未能解决你的问题,请参考以下文章

scala/java读取项目中的文件

读写文件时遇到编码问题解决方法

java文件如何读取

FFmpeg本地任意文件读取漏洞 / FFmpeg Local arbitrary file read vulnerability

Java 的 inputStream 读取文本内容

java文件读取指定内容