i am trying to transfer files via socket. I've used only a single socket for communication( not according to FTP protocol i guess). The following code will transfer the first file successfully but is not able to tra nsfer second file as the filename doesn't change but the server gets the read bytes of the new data file. I think the problem is of the readUTF and writeUTF.
Here is my server side code. Remember this accepts the file.Not send file.
public int listenPort() throws IOException{
System.out.println("LISTENING");
try{
//this.dis = new DataInputStream(this.socketClient.getInputStream());
if( this.dis.available() != 0 ){
String filename = this.dis.readUTF();
this.fos = new FileOutputStream("/home/ankit07/" + filename);
int bytesRead = (int) IOUtils.copyLarge(this.dis,this.fos); //no of bytes copied
return bytesRead;
}else{
return 0;
}
}finally{
}
}
Here is my client side. Remember this side sends the file. Not accept
public void getFile(String filename) throws IOException{
try{
this.file = this.window.file;
DataOutputStream dos = new DataOutputStream(this.socketClient.getOutputStream());
dos.writeUTF(filename);
FileInputStream fis = new FileInputStream(this.file);
int readByte = (int) IOUtils.copyLarge(fis, dos);
System.out.println("FILE SENT : " + filename + " Bytes :" + readByte);
//this.socketClient.close();
}finally{
//if( this.os!=null) this.os.close();
if( this.window.file != null) this.window.file = null;
if( this.file != null) this.file = null;
//if( this.socketClient!=null) this.socketClient.close();
}
}
The file selections are done in other class window.
The method to select the file is in the window class. This has a public File property to hold the file and then i've called the getFile(String filename) to send the file name and to refer to the selected file, the client has File property to refer to the same file.
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
Object src = e.getSource();
if( src instanceof JButton ){ //Browse clicked
JFileChooser fc = new JFileChooser();
int returnVal = fc.showDialog(null, "SELECT FILE");
if( returnVal == JFileChooser.APPROVE_OPTION){
this.file = fc.getSelectedFile();
try {
this.sc.getFile(this.file.getName());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}else{
//unable to select file
}
}
}
Also i am not able to transfer large files like mp3 and video besides my initial problem. It would be helpful if you'd know any solutions.
Thanks you !!!!
You're sending filename, but then you're sending this.file. There's nothing here to show that they're always referring to the same file. Indeed you have a RS file, in this.window.file. You need to sort out all this confusion.
Related
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...
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();
}
}
I'm trying to upload some files to a Local FTP server. The observable list has all the files, and are uploaded by looping the array
I'm using the commons-net-3.6.jar Library.
The Directory and everything get's created but the images uploaded are corrupted. Huge change in color (looks like an old static TV image with colors)
What am i doing wrong?
NOTE! Something I noticed was that the sizes of file's are the same in KB but differs slightly by bytes.
ObservableList<File> uploadFiles = FXCollections.observableArrayList();
FTPClient client = new FTPClient();
InputStream fis = null;
FTPConnection con = new FTPConnection();
con.readData(); //gets username and password
uploadFiles = Something.getFiles(); //Gets Files
try {
client.connect(con.getServerIp());
client.login(con.getUsername(), con.getPassword());
String pathname = getPathname();
client.makeDirectory(pathname);
for (int i = 0; i < uploadFiles.size(); i++) {
fis = new FileInputStream(uploadFiles.get(i));
String filename = uploadFiles.get(i).getName();
String uploadpath = pathname+"/"+filename;
System.out.println("Uploading File : " + uploadpath);
client.storeFile(uploadpath, fis);
}
client.logout();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fis != null) {
fis.close();
}
client.disconnect();
} catch (IOException e) {
e.printStackTrace();
}
}
Setting the file type to Binary did the Trick!
client.setFileType(FTP.BINARY_FILE_TYPE);
I wrote this class (from examples) to download the header of all the files contained in a remote FTP folder. It works well, but when it approaches to download the file #146 it stops with a NullPointException. The file #146 exists and I can download it as a single file actually.
In the method remotePathLong contains all the remote folders written in a single line and spaced with the space character.
public void downloadHeader(String remotePathLong, String destPath, int bytes) {
String remotePath;
FTPFile[] fileList;
String[] fileNameList;
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(server);
ftpClient.login(user, pass);
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
int indice = 0;
int iP = 1;
File downloadFile;
String destFile;
String remoteFile;
byte[] bytesArray;
int bytesRead = -1;
while ((remotePath = getPath(remotePathLong, iP)) != null) {
System.out.println("Loading file list from the server.....");
fileNameList = ftpClient.listNames(remotePath);
for (String file : fileNameList) {
indice += 1;
System.out.println(indice + " - Downloading: " + file);
//Select files
destFile = destPath.concat(file);
downloadFile = new File(destFile);
outputStream = new BufferedOutputStream(new FileOutputStream(downloadFile));
//Download remote file (from ftp)
remoteFile = remotePath.concat(file);
inputStream = ftpClient.retrieveFileStream(remoteFile);
bytesArray = new byte[bytes];
bytesRead = inputStream.read(bytesArray);
outputStream.write(bytesArray);
//Save into file
outputStream.close();
inputStream.close();
iP += 1;
}
}
} catch (IOException ex) {
} final{
try {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
}
catch (IOException ex1) {
System.out.println("Error: " + ex1.getMessage());
}
}
when it reaches bytesRead = inputStream.read(bytesArray), at the iteration #146 it gives the error. But if at the same iteration i reinitialize the connection it works.
Does anybody have a suggestion please?
It is possible your connection times out due to a network traffic or a file size that happens to be 146th.
Can you print the 146th file name and check its size. Also you can increase the FTP connection timeout period
ftpClient.setControlKeepAliveTimeout(300); // set timeout to 5 minutes
in my java Project I have several classes/java files but is in Menu class that is stored all the lists of stuff that is used. In terms of data I store 6 Lists(2 ArrayLists and 4 HashMaps) which 1 is defined in Menu class and others are in different classes.
So I need to create a savestate and a loadstate to when I close the program to restore the previous state. All the Lists are implemented with Serializable
Is it possible to save all the Menu's state and reload it or I've to save all the lists individually? Save all in one file would be great.
Here is the function I have, works(no warnings/errors) and compiles but doesn't creates the file "datafiles".
Any ideas?
private void MenuSave(){
String wd = System.getProperty("user.dir");
JFileChooser fc = new JFileChooser(wd);
int rc = fc.showDialog(null, "Select Data File Location to Save");
if (rc == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
String filename = file.getAbsolutePath();
savestate(lf, lc, lv, lcl,filename);}
}
public void savestate(Cars la, Bikes l2, Motos l3, Planes l4, People n1, Food n2, String filename){
int i;
File out = new File(filename);
ObjectOutputStream output = null;
try{
output = new ObjectOutputStream(new FileOutputStream(filename));
for(Car c : la.getCars().values()){
output.writeObject(c);
}
for(Bike b : l2.getBikes().values()){
output.writeObject(b);
}
for(Moto m : l3.getMotos().values()){
output.writeObject(m);
}
for(i=0;i<n1.size();i++)
{output.writeObject(n1.get(i)));
}
for(i=0;i<n2.size();i++)
{output.writeObject(n2.get(i)));
}
}catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
if (output != null) {
output.flush();
output.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
doesn't creates the file "datafiles".
I'll bet that it does, just not where you are expecting to find it. Don't "drop your files wherever they fall", put them some place that is read/writable, logical and reproducible.
String filename = "datafiles";
File out = new File(System.getProperty("user.home"), filename);
// ...
output = new ObjectOutputStream(new FileOutputStream(out));
Then look in user home for the datafiles (why does it have no file type/extension?) file.
The File constructor that accepts 2 String (parent & name) parameters uses the correct File separator for the OS.
user.home is a system property that points to a stable, reproducible path that has read/write access.
So as I thought I just need to save the lists individually without that for .
1-Choose where to save the file, then save the Classes in there.
2-To read just parse the input and store replacing the current Classes.
...
String wd = System.getProperty("user.dir");
this.setAlwaysOnTop(false);
JFileChooser fc = new JFileChooser(wd);
fc.setDialogType((int)JFileChooser.SAVE_DIALOG);
int rc = fc.showDialog(null, "Select Data File");
this.setAlwaysOnTop(true);
if (rc == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
ObjectOutputStream output = null;
try{
output = new ObjectOutputStream(new FileOutputStream(file));
output.writeObject(list1);
output.writeObject(list2);
output.writeObject(list3);
....
output.close();
}catch (IOException x){
....
}catch(NullPointerException n){
....
}}
to read is just the same:
String wd = System.getProperty("user.dir");
this.setAlwaysOnTop(false);
JFileChooser fc = new JFileChooser(wd);
fc.setDialogType((int)JFileChooser.OPEN_DIALOG);
int rc = fc.showDialog(null, "Select Data File to Load");
this.setAlwaysOnTop(true);
if (rc == JFileChooser.APPROVE_OPTION)
{
File file = fc.getSelectedFile();
String filename = file.getAbsolutePath();
ObjectInputStream input = null;
try{
input = new ObjectInputStream(new FileInputStream(file));
this.list1=(ListType1)input.readObject();
this.list2=(ListType2input.readObject();
....
}catch (IOException x){
...
}catch(ClassNotFoundException x){
...
}
}