使用 SMBJ 客户端将数据附加到现有文件

问题描述

我需要使用 SMBJ 客户端将数据附加到现有文件。下面的代码附加了数据,但最终文件已损坏,无法读取/打开文件

 Set<AccessMask> accessMask = new HashSet<>();
 accessMask.add(AccessMask.GENERIC_READ);
 accessMask.add(AccessMask.GENERIC_WRITE);

 Set<FileAttributes> fileAttributes = new HashSet<>();
 fileAttributes.add(FileAttributes.FILE_ATTRIBUTE_norMAL);

 Set<SMB2CreateOptions> createOptions = new HashSet<>();
 createOptions.add(SMB2CreateOptions.FILE_RANDOM_ACCESS);

 File file = share.openFile("PATH",accessMask,fileAttributes,SMB2ShareAccess.ALL,SMB2Createdisposition.FILE_OPEN_IF,createOptions);

 // Approach - 1
 long fileOffset = 0;
 byte[] buffer = new byte[1024*4];
 int length = inputStream.read(buffer);
 while(length != -1){
   fileOffset = share.getFileinformation("PATH").getStandardinformation().getEndOfFile();
   file.write(buffer,fileOffset,lenght);
 }

//Approach - 2
 OutputStream oStream = f.getoutputStream();
     oStream.write(fileContents.getBytes());
     oStream.flush();
     oStream.close();

但是从这两种方法中,都无法正确附加数据。

解决方法

我是这样做的:

private static void uploadAppend(File source,DiskShare diskShare,String destPath) throws IOException {
    if (source != null && source.exists() && source.canRead()
            && source.isFile()) {

        try (InputStream is = new java.io.FileInputStream(source)) {
            if (destPath != null && is != null) {
                Set<AccessMask> accessMask = new HashSet<>(EnumSet.of(
                        AccessMask.FILE_READ_DATA,AccessMask.FILE_WRITE_DATA,AccessMask.DELETE));
                Set<SMB2ShareAccess> shareAccesses = new HashSet<>(
                        EnumSet.of(SMB2ShareAccess.FILE_SHARE_READ,SMB2ShareAccess.FILE_SHARE_WRITE,SMB2ShareAccess.FILE_SHARE_DELETE));
                Set<FileAttributes> createOptions = new HashSet<>(
                        EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL));

                try (com.hierynomus.smbj.share.File file = diskShare
                        .openFile(destPath,accessMask,createOptions,shareAccesses,SMB2CreateDisposition.FILE_OPEN_IF,EnumSet.noneOf(SMB2CreateOptions.class))) {

                    int bufferSize = 2048;
                    if (source.length() > 20971520l) {
                        bufferSize = 131072;
                    }
                    byte[] buffer = new byte[bufferSize];
                    long fileOffset = 0;
                    int length = 0;
                    while ((length = is.read(buffer)) > 0) {
                        fileOffset = diskShare.getFileInformation(destPath)
                                .getStandardInformation().getEndOfFile();
                        file.write(buffer,fileOffset,length);
                    }
                    file.flush();
                    file.close();
                } finally {
                    is.close();
                }
            }
        }
    }
}
,

以下是 jcifs.smb.SmbFileOutputStreamjcifs.smb.SmbFileInputStream 类的解决方案:

private void AppendToFile() throws Exception {
        CIFSContext base = SingletonContext.getInstance();
        CIFSContext context = base.withCredentials(new NtlmPasswordAuthentication(base,"domainName","userName","password"));
        try (SmbFile f = new SmbFile("smb://serverName/folder/test.txt",context)) {
            SmbFileInputStream in = new SmbFileInputStream(f);
            byte[] buffer = new byte[1024]; //your file size
            int bytesRead = in.read(buffer);
            while (bytesRead > 0) {
                bytesRead = in.read(buffer);
            }
            in.close();

//...
//do your operations with the data in buffer
//...


            SmbFileOutputStream out = f.openOutputStream(true); //true is for append mode
            out.write(buffer);
            out.close();
        }
    }