Pushing multiple files to smb share jcifs from local folder - java

How we can push multiple files from our local folder to smb share folder using java. I can do with my single file using smbFile and it is working. I am looking for pushing multiple file push to smb share.
Any reference links and sample code would be helpful.
Thanks.
EDIT, Reference of code :
SmbFile[] files = getSMBListOfFiles(sb, logger, domain, userName, password, sourcePath, sourcePattern);
if (files == null)
return false;
output(sb, logger, " Source file count: " + files.length);
String destFilename;
FileOutputStream fileOutputStream;
InputStream fileInputStream;
byte[] buf;
int len;
for (SmbFile smbFile: files) {
destFilename = destinationPath + smbFile.getName();
output(sb, logger, " copying " + smbFile.getName());
try {
fileOutputStream = new FileOutputStream(destFilename);
fileInputStream = smbFile.getInputStream();
buf = new byte[16 * 1024 * 1024];
while ((len = fileInputStream.read(buf)) > 0) {
fileOutputStream.write(buf, 0, len);
}
fileInputStream.close();
fileOutputStream.close();
} catch (SmbException e) {
OutputHandler.output(sb, logger, "Exception during copyNetworkFilesToLocal stream to output, SMP issue: " + e.getMessage(), e);
e.printStackTrace();
return false;
}
This works fine if i try to send one single file of anyformat. But if would like to send multiple file to smb share fromocal folder. For This i need thr help please. Thanks.

Try to declare a SmbFile object that is a root folder of your folder, that you want to upload to the shared folder. Then iterate through the root.listFiles() array.
Put the uploadable files in that folder.
I assume that, your SmbFile[] files array only contains one file if it's only uploading one file.
Or another possible solution is that, try to use SmbFileOutputStream and SmbFileInputStream instead of FileOutputStream and FileInputStream.

I'm guessing you are using jcifs-library (which is quite outdated), so firstly I would recommend you to switch library. I switched to SMBJ and here is how I'm uploading file:
private static void upload(File source, DiskShare diskShare, String destPath, boolean overwrite) throws IOException {
try (InputStream is = new java.io.FileInputStream(source)) {
if (destPath != null && is != null) {
// https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files
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_WRITE));
Set<FileAttributes> createOptions = new HashSet<>(
EnumSet.of(FileAttributes.FILE_ATTRIBUTE_NORMAL));
try (com.hierynomus.smbj.share.File file = diskShare
.openFile(destPath, accessMask, createOptions,
shareAccesses,
(overwrite
? SMB2CreateDisposition.FILE_OVERWRITE_IF
: SMB2CreateDisposition.FILE_CREATE),
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, 0, length);
}
file.flush();
file.close();
} finally {
is.close();
}
}
}
}
Of course takes a little effort on connecting the SMB-server and authenticating before this, but that's another case...

Related

How to duplicate a file given a different name in the same directory in windows

I have been trying to duplicate a file but change the name of it in the same windows directory but I got not luck.
I cant just copy the file in the same directory because of the windows rule that two files cannot have the same name in the same directory.
I am not allowed to copy it to another directory then rename it, and then move it back in the same directory.
And I don't see any helpful implementation in the File.class.
Tried something like that but it didnt work:
File file = new File(filePath);
File copiedFile = new File(filePath);
//then rename the copiedFile and then try to copy it
Files.copy(file, copiedFile);
An initial attempt would be using Path as suitable:
Path file = Paths.get(filePath);
String name = file.getFileName().toString();
String copiedName = name.replaceFirst("(\\.[^\\.]*)?$", "-copy$0");
Path copiedFile = file.resolveSibling(copiedName);
try {
Files.copy(file, copiedFile);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
You could create a new file in the same directory and then just copy the contents of the original file to the duplicate
See: Java read from one file and write into another file using methods
For more info
you can also use this snippet from https://www.journaldev.com/861/java-copy-file
private static void copyFileUsingStream(File source, File dest) throws IOException {
InputStream is = null;
OutputStream os = null;
try {
is = new FileInputStream(source);
os = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
} finally {
is.close();
os.close();
}
}
#Pierre his code is perfect, however this is what I use so I won't be able to change the extension:
public static void copyWithDifferentName(File sourceFile, String newFileName) {
if (sourceFile == null || newFileName == null || newFileName.isEmpty()) {
return;
}
String extension = "";
if (sourceFile.getName().split("\\.").length > 1) {
extension = sourceFile.getName().split("\\.")[sourceFile.getName().split("\\.").length - 1];
}
String path = sourceFile.getAbsolutePath();
String newPath = path.substring(0, path.length() - sourceFile.getName().length()) + newFileName;
if (!extension.isEmpty()) {
newPath += "." + extension;
}
try (OutputStream out = new FileOutputStream(newPath)) {
Files.copy(sourceFile.toPath(), out);
} catch (IOException e) {
e.printStackTrace();
}
}

Zip File md5 Checksum - Every Time Different

I have an Android applications which gets zip file's md5 checksum. I use it to compare the file with file on a server. My problem is that every time I try to generate the md5 for the same file, the checksum is different. I'm posting my methods here. Can you tell me what is wrong?
private static String fileMD5(String filePath) throws NoSuchAlgorithmException, IOException {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(filePath);
byte[] buffer = new byte[1024];
MessageDigest digest = MessageDigest.getInstance("MD5");
int numRead = 0;
while (numRead != -1) {
numRead = inputStream.read(buffer);
if (numRead > 0)
digest.update(buffer, 0, numRead);
}
byte [] md5Bytes = digest.digest();
return convertHashToString(md5Bytes);
} catch (Exception e) {
return "ERROR";
} finally {
if (inputStream != null) {
try {
inputStream.close();
} catch (Exception e) { }
}
}
}
private static String convertHashToString(byte[] md5Bytes) {
String returnVal = "";
for (int i = 0; i < md5Bytes.length; i++) {
returnVal += Integer.toString(( md5Bytes[i] & 0xff ) + 0x100, 16).substring(1);
}
return returnVal;
}
i try to solve same issue. I don't know how to solve it but I know reason :).
Reason is that zip file contains at least timestamp information about files. And this is what change you md5sum. Every zip entry is the same but this metadata information change result for md5.
Probably you already find answer somewhere else.
As #michal-Šiplák mentioned
Reason is that zip file contains at least timestamp information about
files. And this is what changes your md5sum. Every zip entry is the same
but this metadata information change result for md5.
To have consistent md5 you need to remove this variable and have it fixed as a constant. Bellow example
fun pack(sourceDir: File, zipFile: File) {
ZipOutputStream(zipFile.outputStream()).use { zs ->
val sourcePath = sourceDir.toPath()
Files.walk(sourcePath)
.filter { path -> path.isDirectory().not() }
.forEach { path ->
zs.putNextEntry(createZipEntry(path, sourcePath))
Files.copy(path, zs)
zs.closeEntry()
}
}
}
fun createZipEntry(filePath: Path, sourcePath: Path): ZipEntry {
val zipEntry = ZipEntry(sourcePath.relativize(filePath).toString())
zipEntry.time = 0
return zipEntry
}
key Line here is zipEntry.time = 0 which makes metadata zip file constant.

Download a text file from the web - Android/ Java

I'm trying to get save a text file from the internet into a folder in my res directory (res/files) so I can then read and interpret it. My android manifest has set the appropiate permissions but when I test it in the simulator it fails.
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
Here's the method to get the file:
public void getTextFile(){
String path ="http://hullmc.org.uk/cjvize/test.txt";
URL u = null;
try {
u = new URL(path);
BufferedReader in = new BufferedReader(new InputStreamReader(u.openStream()));
int i = 0;
String replicated = "";
do{
String str = in.readLine();
replicated = replicated + "/n" + str;
i++;
}while(i<85);
in.close();
}
catch(Exception e){
welcome.setText("Failed");
}
}
Can anyone suggest why this is not working? Many thanks!
This is working fine for me :
Use of class variable for View and Activity allow to keep code centralaized and shared, passing view as parameter, updated in constructor :)
1) Code to store the file locally
View newReport;
Activity reportActivity;
private void downloadFile(String fileUrl, String fileName) {
try{
InputStream is = (InputStream) new URL(fileUrl).getContent();
FileOutputStream output = reportActivity.openFileOutput(fileName, newReport.getContext().MODE_PRIVATE);
byte data[] = new byte[1024];
int count;
while ((count = is.read(data)) != -1)
output.write(data, 0, count);
output.flush();
output.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
It saves the file on the internal storage.
Then to save a file from URL, just call:
downloadFile(myFileUrl, mySaveToFileName);
And to list your local files available:
String[] fileList = newReport.getContext().fileList();
for (String s : fileList){
System.out.println("File found : "+s);
}
Note: you do not require to save it locally to read it. If you prefer just to read it (to extract some info), let me know.
2) Code to "read and save to database", this should resolve:
// After InputStream declaration:
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null)
{
//TODO Update database row concatenating inputLine to existing text value.
}
in.close();
in=null;
is.close();
you can't save into the resource folder of your app. you can't even store files into the assets folder.
there aren't even such folders when you install the app - they are all zipped into the APK . the res folder is a special one too, because each file there also creates a constant in the "R.java" file, so that it would be easier to reach and use. you can't reach such a thing when it's dynamic...
what you can do is to choose the right folder for you (read here), and download the file into there, using something like this :
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream(fullFilePath);
byte data[] = new byte[1024];
int count;
while ((count = input.read(data)) != -1)
output.write(data, 0, count);
//todo close streams and handle exceptions
if you use Apache commons library, you could minimize the code to just one line:
IOUtils.copy(new BufferedInputStream(url.openStream()), new FileOutputStream(fullFilePath));

Alternative to move files

I wonder if there is any other way to move files from one directory to another, a snippet of my program is below. I believe there should be an efficient way to move files in java. Please take a look and respond if possible. Thanks!
public static void movFile(File pathFromMove,File pathToMove,File fileToMove) //helper method 2
{
String absPathFile2= pathToMove.getAbsolutePath() + "\\"+fileToMove.getName(); //{
InputStream inStream = null;
OutputStream outStream = null;
try
{
//System.out.println("i am here no1");
inStream= new FileInputStream(fileToMove);
outStream=new FileOutputStream(absPathFile2);
byte[] buffer = new byte[1024];
int length;
while (( length = inStream.read(buffer)) > 0)
{
outStream.write(buffer, 0, length);
//System.out.println("i am here no2");
}
inStream.close();
outStream.close();
fileToMove.delete(); //to delete the original files
// System.out.println("i am here no3");
}
catch(IOException e)
{
//System.out.println("i am here no4");
e.printStackTrace();
}
}
If it's on the same disk, the File.renameTo would be efficient
I'm not sure why you would need 3 File references, two should be enough...but it's your code...
For example...
public static void movFile(File pathFromMove,File pathToMove,File fileToMove) throws IOException {
File from = new File(pathFromMove + File.separator + fileToMove);
File to = new File(pathToMove+ File.separator + fileToMove);
if (!from.renameTo(to)) {
throw new IOException("Failed to move " + from + " to " + to);
}
}
You can alos have a look at Moving a File or Directory which uses the new Paths API available in Java 7

Decompressing tar file with Apache Commons Compress

I'm using Apache Commons Compress to create tar archives and decompress them. My problems start with this method:
private void decompressFile(File file) throws IOException {
logger.info("Decompressing " + file.getName());
BufferedOutputStream outputStream = null;
TarArchiveInputStream tarInputStream = null;
try {
tarInputStream = new TarArchiveInputStream(
new FileInputStream(file));
TarArchiveEntry entry;
while ((entry = tarInputStream.getNextTarEntry()) != null) {
if (!entry.isDirectory()) {
File compressedFile = entry.getFile();
File tempFile = File.createTempFile(
compressedFile.getName(), "");
byte[] buffer = new byte[BUFFER_MAX_SIZE];
outputStream = new BufferedOutputStream(
new FileOutputStream(tempFile), BUFFER_MAX_SIZE);
int count = 0;
while ((count = tarInputStream.read(buffer, 0, BUFFER_MAX_SIZE)) != -1) {
outputStream.write(buffer, 0, count);
}
}
deleteFile(file);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (outputStream != null) {
outputStream.flush();
outputStream.close();
}
}
}
Every time I run the code, compressedFile variable is null, but the while loop is iterating over all entries in my test tar.
Could you help me to understand what I'm doing wrong?
From the official documentation
Reading entries from an tar archive:
TarArchiveEntry entry = tarInput.getNextTarEntry();
byte[] content = new byte[entry.getSize()];
LOOP UNTIL entry.getSize() HAS BEEN READ {
tarInput.read(content, offset, content.length - offset);
}
I have written an example starting from your implementation and testing with a very trivial .tar (just one entry of text).
Not knowing the exact requirement I just take care of solving the problem of reading the archive avoiding the nullpointer. Debugging, the entry is available as you also have found
private static void decompressFile(File file) throws IOException {
BufferedOutputStream outputStream = null;
TarArchiveInputStream tarInputStream = null;
try {
tarInputStream = new TarArchiveInputStream(
new FileInputStream(file));
TarArchiveEntry entry;
while ((entry = tarInputStream.getNextTarEntry()) != null) {
if (!entry.isDirectory()) {
File compressedFile = entry.getFile();
String name = entry.getName();
int size = 0;
int c;
while (size < entry.getSize()) {
c = tarInputStream.read();
System.out.print((char) c);
size++;
}
(.......)
AS I said: I tested with a tar including only an entry of text (you can also try this approach to verify the code) to be sure that the null is avoided.
You need to make all the needed adaptations for your real needs.
It is clear that you will have to handle streams as in the metacode I posted on top.
It shows how to deal with the single entries.
Try using getNextEntry() method instead of getNextTarEntry() method.
The second method returns a TarArchiveEntry. Probably this is not what you want!

Categories