问题描述
我需要使用 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.SmbFileOutputStream
和 jcifs.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();
}
}