上一篇文章我们已经介绍了解决文件乱码的一种方式——修改Eclipse设置,但修改Eclipse设置并未改变文件编码格式,有时候我们需要统一文件编码格式,这时候就需要用到第二种解决文件乱码的方式——文件转码。下面介绍两种方式实现文件转码。
一、Eclipse插件实现文件转码
这个需要我们下载一个Eclipse文件转码插件com.lifesting.tool.encoding_1.0.0.jar,下载链接及教程可参考下面这篇文章http://www.blogjava.net/lifesting/archive/2008/04/11/192250.html,这里就不多介绍了。
二、自己编写程序实现文件转码
我们知道,文件出现乱码主要是因为文件的编码和解码方式不一致,前面写入数据的时候我们可能用的是GBK格式,而后面读取的时候却可能用了别的格式(如UTF-8),这样就极可能出现乱码,尤其是包含了中文字符的文件。
其实,在我们知道了乱码产生的原因后,我们就可以自己动手编写一个文件转码程序。
String类有一个构造方法String(byte [ ] bytes,String charsetName)和一种获取指定码表的字节数组的方法getBytes(String chasetName),通过这两种方法我们就可以实现字符串的转码,示例如下:
String str=new String("汉字".getBytes("GBK"),"UTF-8");
而这里我们需要实现整个文本内容的转码,整体思路其实差不多,不过得用到转换流的一些知识InputStreamReader(InputString in,String chasetName)和OutputStreamWriter(OutputString out,String chasetName),有了这两个方法后,剩下我们需要掌握的就是一些文本的操作了,可以参考文章——IO学习之File类https://blog.csdn.net/LIAO_7053/article/details/81940835。
三、java代码实现
1、功能实现:
a.批量文件编码格式转换;
b.文件夹遍历后指定位置输出;
c.方便友好的操作界面
2、具体代码:
package com.liao.CodeTools0823;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
public class MainUI extends JFrame {
private static final long serialVersionUID = 518541171932584910L;
private JTextField jtf1;
private JTextField jtf2;
private JComboBox<String> jcb1;
private JComboBox<String> jcb2;
private JButton jbu;
private ArrayList<File> filelist = new ArrayList<>();// 存储文件队列
//主函数
public static void main(String[] args) {
MainUI mui = new MainUI();
mui.init();
mui.listen();
}
// 界面设计
public void init() {
setTitle("文件转码");
setSize(340, 210);
setLocationRelativeTo(null);
setLayout(new FlowLayout());
setResizable(false);
setDefaultCloseOperation(3);
// 原文件编码标签
JLabel jl2 = new JLabel("原文件编码");
add(jl2);
// 支持的编码格式
String[] encodeTypes = { "GBK", "UTF-8", "Unicode", "ASCII", "GB2312" };
// 原文件编码
jcb1 = new JComboBox<>(encodeTypes);
add(jcb1);
// 目标文件编码标签
JLabel jl4 = new JLabel("目标文件编码");
add(jl4);
// 目标文件编码
jcb2 = new JComboBox<>(encodeTypes);
add(jcb2);
// 原文件地址标签
JLabel jl1 = new JLabel("原文件地址");
add(jl1);
// 原文件地址
jtf1 = new JTextField(28);
add(jtf1);
// 目标文件地址标签
JLabel jl3 = new JLabel("目标文件地址");
add(jl3);
// 目标文件地址
jtf2 = new JTextField(28);
add(jtf2);
// 开始按钮
jbu = new JButton("开始");
add(jbu);
setVisible(true);
}
// 监听器获取信息
private void listen() {
// 添加监听器
jbu.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 获取地址、编码信息
String originalDir = jtf1.getText();
String targetDir = jtf2.getText();
String type1 = jcb1.getSelectedItem().toString();
String type2 = jcb2.getSelectedItem().toString();
// 调用文件判断方法及编码方法
if (judge(originalDir, targetDir)) {
encode(type1, type2, targetDir);
}
}
});
}
// 对原文件进行判断
private Boolean judge(String originalDir, String targetDir) {
File file1 = new File(originalDir);
// 判断原文件是否存在
while (!file1.exists()) {
JOptionPane.showMessageDialog(null, "输入文件不存在");
return false;
}
if (file1.isFile()) {
filelist.add(file1);
// 创建新的File对象,指定存储位置
File file2 = new File(targetDir);
// 文件目录存在则创建
if (!file2.exists()) {
file2.mkdir();
}
} else {
// 创建新的File对象,指定存储位置
File file2 = new File(targetDir, originalDir);
// 调用遍历文件方法
getFile(file1, file2);
}
return true;
}
// 遍历文件夹
private void getFile(File dir1, File dir2) {
// 文件夹不存在,则创建文件
if (!dir2.exists()) {
dir2.mkdirs();
}
// 获取该目录下文件数组
File[] files = dir1.listFiles();
// 遍历文件数组
for (File file : files) {
if (file.isDirectory()) {
// 创建新的文件对象,指定保存路径
File dir = new File(dir2, file.getName());
// 递归调用
getFile(file, dir);
} else {
// 添加至文件队列中
filelist.add(file);
}
}
}
// 编码方法
private void encode(String type1, String type2, String targetDir) {
// 给队列中文件编码
for (File file : filelist) {
File file3;
// 按原文件结构指定新文件的路径
if (file.getParent() != null) {
file3 = new File(targetDir + "\\" + file.getParent(), file.getName());
} else {
file3 = new File(targetDir, file.getName());
}
try {
// 创建指定编码格式的字节转换流
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), type1);
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file3), type2);
// 使用缓冲流对文件进行读写
BufferedReader br = new BufferedReader(isr);
BufferedWriter bw = new BufferedWriter(osw);
String line;
// 读写文件
while ((line = br.readLine()) != null) {
bw.write(line);
bw.flush();
bw.newLine();
}
br.close();// 关闭输入流
bw.close();// 关闭输出流
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
// 编码完成提示信息
JOptionPane.showMessageDialog(null, "编码完成!");
}
}
注意事项:
1、对原文件进行判断:是否存在?文件还是目录?
2、地址使用:绝对地址还是相对地址?这里小编为了方便操作采用的是相对地址;
3、本文保存文件是在一个指定文件夹里按原文件结构进行保存;
4、使用readLine( )读取文件时,写入文件的时候需要注意换行。
四、小结
本文主要介绍了两种文件转码的方式,下载Eclipse插件和自己编写小程序,两种方式均可以达到批量文件转码的效果。使用Eclipse插件操作简单,不过可能会遇到一些小bug;而自己写小程序则更有成就感,用起来也更得心应手,不过需要熟练掌握转换流及文件操作等相关知识。