Java реализует нарезку и склеивание файлов.

Java задняя часть Linux Windows

Java реализует разделение и склеивание файлов.

Однопоточная реализация

разделить файл

В старой файловой системе FAT32 наибольший размер отдельного файла необходимо сохранять в 4G, что не позволяет часто читать фильм. Но теперь у Windows есть файловые системы NTFS, большая часть Linux — это файловая система EXT4, а максимальный размер одного файла может превышать 4G. Однако и то, и другое несовместимо. . Формат NTFS U-диск Linux не может идентифицировать, форматирование U-диска Windows из EXT4 не может быть идентифицировано и может быть совместимо только со старой FAT32. Поэтому важно разбить файл, а потом очень важен прошивка.Файл разбивается на сеть.

Недавно читал Брэда Питта из "Ярости".

Во-первых: разделение файла требует определения размера каждой части, предполагая вышеизложенноеFury.mkvРазмер файла280M, разделите каждый блок и установите размер по умолчанию равным64M,так:

Для последнего блока, как правило, меньше или равно установленному по умолчанию размеру каждого блока. Задается размер каждого блока, далее нужно получить путь к файлу, построить входной поток в коде, прочитать файл в буфер памяти, а затем построить выходной поток для вывода буфера в новый сплит файл. Следующая реализация очень проста. создать новыйFileSliceКласс: Существуют методы резки и методы сращивания.

public class FileSlice {
    /**
     * 分割文件
     * @param filePath 文件路径
     * @param filePieceSize 文件每块大小,单位为字节,为-1则默认为每块64M
     * @return 成功返回True,出错则返回False
     */
    public static boolean slice(Path filePath, int filePieceSize){
        return true;
    }

    /**
     * 将分割好的文件重新链接
     * @param filePath 被分割好的其中之一文件路径,默认其他块与其在同一目录下
     * @param howManyParts 一共有多少块
     * @return 成功返回True,出错则返回False
     */
    public static boolean glue(Path filePath, int howManyParts){
        return true;
    }
}

Далее реализуем метод однопоточной сегментации: Графически это должно выглядеть так:

Код: Сначала введите функцию, чтобы определить, существует ли файл:

if (!Files.exists(filePath)){
    return false;
}

Затем определите, следует ли использовать значение по умолчанию для каждого размера блока:

if(filePieceSize == -1){
    filePieceSize = 1024*1024*64;
}

Преобразуйте путь в файловый объект, затем рассчитайте, сколько блоков будет разделено:

File file = filePath.toFile();
int howManyParts = (int) Math.ceil(file.length() / (double)filePieceSize);

Инициализировать потоки ввода и вывода, вывести сообщение об ошибке при ошибке, вернуть false и получить текущий каталог:

DataInputStream fileReader = null;
try {
    fileReader = new DataInputStream(new FileInputStream(file));
} catch (FileNotFoundException e) {
    e.printStackTrace();
    System.out.println("文件找不到!");
    return false;
}
DataOutputStream fileWriter;
Path dir = filePath.getParent();

Затем прочитайте файл и выведите его в каждый файл детали:

int readLength = -1;
long total = 0;

try {
    for (int i = 1; i <= howManyParts ; i++){
        //新建文件part i
        Path temp = Files.createFile(dir.resolve(filePath.getFileName() + ".part" + i));
        //搭建输出流
        fileWriter = new DataOutputStream(new FileOutputStream(temp.toFile()));
        //读取文件并输出
        while ( (readLength = fileReader.read(buffer)) != -1){
            fileWriter.write(buffer,0,readLength);
            fileWriter.flush();
            total += readLength;
            if (total == filePieceSize){
                total = 0;
                break;
            }
        }
        //part i的文件已经输出完毕,关闭流
        fileWriter.close();
    }
    //读取完毕,关闭输入流
    fileReader.close();
} catch (IOException e) {
    e.printStackTrace();
    System.out.println("IO错误!");
    return false;
}

Функцию реализовали, и следующий тест (т.к. в фильме Fury 14G... слишком большой... давайте изменим):

Я пятый эпизод Большого Брата, с 729M, и его можно разделить на 12 частей.

public static void main(String[] args) throws IOException {
    double before = System.currentTimeMillis();

    Path bigboss = Paths.get("D:\\Video\\我是大哥大\\我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4");

    FileSlice.slice(bigboss,-1);

    double after = System.currentTimeMillis();

    System.out.println("分割文件我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4," + Files.size(bigboss) + "字节,总用时" + (after - before) + "ms" );

}

результат операции:

分割文件我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4,765321889字节,总用时16335.0ms

Скорость по-прежнему довольно низкая. . В следующий раз заменю на многопоточность, а потом протестирую скорость. В случае одиночного потока обычная 40-минутная японская дорама будет идти порядка 15-30с, а если это фильм в формате mkv, то долго. . Но на самом деле пределом должна быть не скорость выполнения в ЦП, а IO жёсткого диска.Если это обычный жёсткий диск, пусть даже и многопоточный, он не должен быть намного быстрее. .

сращивание файлов

Это очень просто, и противоположное делению нормально. Перейдите непосредственно к полному коду:

public static boolean glue(Path filePath, int howManyParts){
    if (!Files.exists(filePath)){
        return false;
    }
    //获取原始文件名
    String filename = getOriginalFileName(filePath.getFileName().toString());

    if (filename == null){
        System.out.println("传入part文件名解析出错!");
        return false;
    }
    //初始化缓冲区
    byte [] buffer = new byte[1024 * 8];
    //获取文件存储的路径
    Path dir = filePath.getParent();

    try {
        DataInputStream fileReader  = null;
        //创建原始文件
        Files.createFile(dir.resolve(filename));
        //搭建原始文件输出流
        DataOutputStream fileWriter = new DataOutputStream(new FileOutputStream(dir.resolve(filename).toFile()));

        int readLength = -1;
        for (int i = 1; i <= howManyParts ; i++){
            //得到part i文件路径
            Path temp = dir.resolve(filename + ".part" + i);
            //搭建输入流
            fileReader = new DataInputStream(new FileInputStream(temp.toFile()));
            //读取文件并输出
            while ( (readLength = fileReader.read(buffer)) != -1){
                fileWriter.write(buffer,0,readLength);
                fileWriter.flush();
            }
            //part i的文件已经读入完毕,关闭流
            fileReader.close();
        }
        //写入完毕,关闭输出流
        fileWriter.close();
    } catch (IOException e) {
        e.printStackTrace();
        System.out.println("IO错误!");
        return false;
    }
    return true;
}

Перепроверьте только что расколотую серию I am Big Brother Episode 5.

public static void main(String[] args) throws IOException {
    double before = System.currentTimeMillis();

    Path bigboss = Paths.get("D:\\Video\\我是大哥大\\我是大哥大.Kyou.kara.Ore.wa.Ep05.Chi_Jap.HDTVrip.1280X720.mp4.part1");

    FileSlice.glue(bigboss,12);

    double after = System.currentTimeMillis();

    System.out.println("拼接12个part,用时" + (after - before) + "ms");

}

Вывод результата занимает около 12 секунд, что нормально.

拼接12个part,用时12147.0ms

Воспроизведение открывается без проблем, диаграмма последнего разреза.

Продолжение следует. . Следующее должно быть достигнуто с использованием нескольких потоков.