删除字幕文件中的中文[(匹配中文的正则表达式/获取文件的编码格式)]

匹配中文的正则表达式: [\u4e00-\u9fa5]


前天我在看美剧《权力的游戏》的时候,发现没字幕,于是乎自己从网上下载字幕匹配到视频;发现网上的字幕都是比较全面的,中英双语字幕,但是对我来说,中文字幕是我不想要的,我要强迫自己只看英文字幕,但是在播放器设置上又无法只显示英文;所以只有通过修改字幕文件,将中文删除喽;
本以为一个正则表达式 * 就可以把中文给匹配掉的,但事情并没有那么简单,因为一般带中文的文件有GBK,Unicode,UTF-8,UTF-16……好几种。所以在读取文件和写入文件的时候都需要指定编码格式.
一开始我以为10集的字幕都是同一种编码格式的(Unicode)(可以通过另存为查看到文件的编码格式;),所以我就用unicode解析文件,发现第一个字幕文件可以修改成功,但是后来的9个字幕文件都出现了乱码;查看发现后面的几个文件的编码不是Unicode,有UTF-8和ANSI两种,这时候我就想了,怎么样可以通过一个程序得到一个文件的编码格式呢, 这时候就省力了,最后百度了一下,果然找到了答案;

1.字幕文件片段:

Dialogue: 0,0:54:02.00,0:54:04.86,*Default,NTP,0000,0000,0000,,我欠您一条命 先生\N{\fs16}I owe you my life, ser.{\r}
Dialogue: 0,0:54:04.90,0:54:06.53,*Default,NTP,0000,0000,0000,,我深感荣幸\N{\fs16}The honor is mine,{\r}
Dialogue: 0,0:54:06.57,0:54:08.77,*Default,NTP,0000,0000,0000,,女王陛下\N{\fs16}my queen.{\r}
Dialogue: 0,0:54:12.14,0:54:14.41,*Default,NTP,0000,0000,0000,,你认识他?\N{\fs16}You know this man?{\r}
Dialogue: 0,0:54:14.44,0:54:16.24,*Default,NTP,0000,0000,0000,,我认识他\N{\fs16}I know him{\r}

其中,我要去掉文件的中文字符;也就是介于0000,,和\N{\fs16}之间的这部分;

2.代码片段为:

niuStr = lineStr.replaceAll("(0000,,)(.*)[\u4e00-\u9fa5]*(.)*(\\\\N(\\{\\\\fs16\\})*)", "$1");

其中,[\u4e00-\u9fa5]是匹配一个中文的正则表达式;

3.另外还有一些字幕的格式是这样的:

Dialogue: 0,0:51:52.55,0:51:54.42,正文,,0,0,0,,哦 好的 好的 这样感觉很——\N{\fs16}Oh, yes. Yes, this will do nic--{\r}
Dialogue: 0,0:51:54.45,0:51:56.55,正文,,0,0,0,,啊!\N{\fs16}ah!{\r}
Dialogue: 0,0:51:56.59,0:51:58.76,正文,,0,0,0,,趴上去\N{\fs16}On the stump.{\r}
Dialogue: 0,0:52:04.43,0:52:08.07,正文,,0,0,0,,你觉得你是这里面脑瓜子最灵光的?\N{\fs16}You think you're the smartest man there is.{\r}

4.修改字幕的代码:

niuStr = lineStr.replaceAll("([\u4e00-\u9fa5]*,,0,0,0,,)(.*)[\u4e00-\u9fa5]*(.)*(\\\\N(\\{\\\\fs16\\})*)", "$1");

第一个[\u4e00-\u9fa5]匹配正文两个字,第二个[\u4e00-\u9fa5]匹配中文字幕;

5.上面提到修改文件时还要知道文件的编码格式,我在网上找了一个简单的判断程序,虽然功能有待完善,但已经基本满足我的需求:

/*这个方法用来获取文件的编码格式,功能有限,只能识别UTF-8,Unicode,UTF-16BE如果都不满足,默认返回编码方式为GBK*/
public static String getFileEncoding(File file) throws Exception {
        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
        int p = (bin.read() << 8) + bin.read();//核心代码 

        String encoding = null;

        switch (p) {
        case 0xefbb:
            encoding = "UTF-8";
            break;
        case 0xfffe:
            encoding = "Unicode";
            break;
        case 0xfeff:
            encoding = "UTF-16BE";
            break;
        default:
            encoding = "GBK";
        }
        System.out.println(encoding);
        return encoding;
    }

这部分代码完成获取编码格式的功能;

6.完整的程序代码我给列出来:

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.junit.Test;

public class TrimChineseCaptions {

    /**
     *除去中文字幕
     * 
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        File srcDir = new File("E:\\BaiduYun\\权力的游戏无删减\\字幕\\[zmk.tw]Game.Of.Thrones.S03");// 字幕文件夹
        File[] files = srcDir.listFiles();
        for (File file : files) {// 遍历修改
            File srcFile = file;
            File destFile = null;
            if (srcFile.exists()) {
                String fileName = srcFile.getName();
                destFile = new File(srcFile.getParentFile(), fileName.substring(0, fileName.length() - 4) + "-TrimedChi-S3.ass");//新文件的文件名
            }
            String encoding = getFileEncoding(file);// 获取文件的编码格式

            BufferedReader bufRer = new BufferedReader(new InputStreamReader(new FileInputStream(srcFile), encoding));
            BufferedWriter bufWer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(destFile), encoding));

            String lineStr = null;//读取的string
            String niuStr = null;//替换后的string
            while ((lineStr = bufRer.readLine()) != null) {
                niuStr = lineStr.replaceAll("([\u4e00-\u9fa5]*,,0,0,0,,)(.*)[\u4e00-\u9fa5]*(.)*(\\\\N(\\{\\\\fs16\\})*)", "$1");
                if (niuStr.equals(lineStr)) {
                    niuStr = lineStr.replaceAll("(0000,,)(.*)[\u4e00-\u9fa5]*(.)*(\\\\N(\\{\\\\fs16\\})*)", "$1");
                }
                // System.out.println(niuStr);
                bufWer.write(niuStr);
                bufWer.newLine();
                bufWer.flush();
            }

            bufWer.close();
            bufRer.close();
        }

    }

    /**
     * 这个方法用来获取文件的编码格式,功能有限,只能识别UTF-8,Unicode,UTF-16BE如果都不满足,默认返回编码方式为GBK
     * 
     * @param file
     * @return encoding : 文件的编码格式
     * @throws Exception
     */
    public static String getFileEncoding(File file) throws Exception {
        BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
        int p = (bin.read() << 8) + bin.read();//核心代码 

        String encoding = null;

        switch (p) {
        case 0xefbb:
            encoding = "UTF-8";
            break;
        case 0xfffe:
            encoding = "Unicode";
            break;
        case 0xfeff:
            encoding = "UTF-16BE";
            break;
        default:
            encoding = "GBK";
        }
        System.out.println(encoding);
        return encoding;
    }

    // @Test
    public void test_o2() {// 匹配中文的正则表达式测试

        String str = "123abc你好efc";

        String reg = "[\u4e00-\u9fa5]";// 匹配中文

        Pattern pat = Pattern.compile(reg);

        Matcher mat = pat.matcher(str);

        String repickStr = mat.replaceAll("");

        System.out.println("去中文后:" + repickStr);

    }
}

版权声明:本文为Love_Legain原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。