So om working my way trough a task in my java-course at school. For better understanding of what the code is supposed to do ill quote it:
"(Split files) Suppose you want to back up a huge file(e.g., a 10-GB AVI file) to a CD-R. You can achieve it by splitting the file into smaller pieces and backing up these pieces separately. Write a utility program that splits a large file into smaller ones using the following command: java ClassName SourceFile numberOfPieces
The command creates the files SourceFile.1, SourceFile2...etc
Now to be clear. This post is in no way an attempt to get a "solution" for the problem. I have solved it (with what i know). And i merely want to get more enlightned on some matters that crossed my mind when writing the code.
Is it neccesary to create a new output for every single file im
copying to? Doesn`t this demand unneccesary system power?
The first file that gets copied(SourceFile is in this case a .png
file) is possible to view. And show a fraction of the original
picture. (If i split into two. i can view half the picture.) But
the latter ones i cant view.. Why is that?
Is it possible to reassemble the splitted files in any way? if my
pictures was split into two files, can i put them back together and
view the whole picture?
The code, if you want to look at it.
All feedback is welcome,
Have a good day! :)
package oblig2;
import java.io.*;
import java.util.*;
public class Test {
/**
* Main method
*
* #param args[0] for source file
* #param args[1] for number of pieces
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// The program needs to be executed with two parameters in order to
// work. This sentence check for it.
if (args.length != 2) {
System.out.println("Usage: java Copy sourceFile numberOfPieces");
System.exit(1);
}
// Check whether or not the sourcefile exists
File sourceFile = new File(args[0]);
if (!sourceFile.exists()) {
System.out.println("Source file " + args[0] + " does not exist");
System.exit(2);
}
// Need an Array to store all the new files that is supposed to contain
// parts of the original file
ArrayList<File> fileArray = new ArrayList<File>();
// All the new files need their own output(or do they?)
ArrayList<BufferedOutputStream> outputArray = new ArrayList<BufferedOutputStream>();
// Using randomAccessFile on the sourcefile to easier read parts of it
RandomAccessFile inOutSourceFile = new RandomAccessFile(sourceFile,
"rw");
// This loop changes the name for the new files, so they match the
// sourcefile with an appended digit
for (int i = 0; i < Integer.parseInt(args[1]); i++) {
String nameAppender = String.valueOf(i);
String nameBuilder;
int suffix = args[0].indexOf(".");
nameBuilder = args[0].substring(0, suffix);
fileArray.add((new File(nameBuilder + nameAppender + ".dat")));
}
// Here i create the output needed for all the new files
for (int i = 0; i < Integer.parseInt(args[1]); i++) {
outputArray.add(new BufferedOutputStream(new FileOutputStream(
new File(fileArray.get(i).getAbsolutePath()))));
}
// Now i determine in how many parts the sourcefile needs to be split,
// and the size of each.
float size = inOutSourceFile.length();
double parts = Integer.parseInt(args[1]);
double partSize = size / parts;
int r, numberOfBytesCopied = 0;
// This loop actually does the job of copying the parts into the new
// files
for (int i = 1; i <= parts; i++) {
while (inOutSourceFile.getFilePointer() < partSize * i) {
r = inOutSourceFile.readByte();
outputArray.get(i - 1).write((byte) r);
numberOfBytesCopied++;
}
}
// Here i close the input and outputs
inOutSourceFile.close();
for (int i = 0; i < parts; i++) {
outputArray.get(i).close();
}
// Display the operations
System.out.println(args[0] + " Has been split into " + args[1]
+ " pieces. " + "\n" + "Each file containig " + partSize
+ " Bytes each.");
}
}
Of course it is necessary to open all output files. But you don't have to open them at all times. You can open the first file, write to it, close it, open the second file, write to it, close it, etc.
File format, .png for example, have a structure that have to follow. It may have special header, and may have special footer. That's why when this file split into two or more, the first will lose its footer, the middle will lose its header and footer, and the last will lose it's header. This make them unusable as individual file.
Of course it is possible. By combining back all the parts, the original file fill be restructured.
Related
I've looked through "similar" questions but wasn't able to get an answer to mine. Please point me to one if it already exists.
Problem: when saving String/StringBuilder to HTML format it adds additional characters at the beginning of the page and I can't figure out why. Example:
’tX<!DOCTYPE html>
<html>
method:
public void saveToHTML(){
String fileName = "";
if (docName != null){
fileName += docName;
} else {
fileName += stdFileName;
}
fileName += "HTML.html";
String tempText = new String("<!DOCTYPE html>\n<html>\n\t<body>");
int tabCount = 3;
for (int oneSec = 0; oneSec < allSections.size(); oneSec++){
for (int onePar = 0; onePar < allSections.get(oneSec).getCountParagraphs(); onePar++){
tempText += (convertParToHTML(allSections.get(oneSec).getParagraph(onePar),
tabCount));
}
}
tempText += ("\n\t</body>\n</html>");
serializeDoc(fileName, tempText.toString());
}
serializeDoc() below:
/**
* Helper method to serialize files
*
* #param fileName name of the file to be saved with
* #param object object to be saved in the file
* #throws IOException
*/
private void serializeDoc(String fileName, Object object){
try {
FileOutputStream file = new FileOutputStream(fileName);
ObjectOutputStream out = new ObjectOutputStream(file);
out.writeObject(object);
out.close();
} catch (IOException e){
System.out.println("The file couldn't be created");
}
}
You haven't posted serializeDoc so we really can't say. But this I will tell you: You really need to keep track of your charset with text files. Outputting the same text in ascii, latin-1, utf-8, utf-16, etc will give you different file sizes and different results. The best way to ensure conformity is to use FileWriters and FileReaders, where you can declare the charset type
-- update --
Yikes yikes and YIKES! You do NOT want to use object serialization here. This is going to save your java objects directly to the file, making the file harder to read and manually adjust. Writing the bytes to the FileOutputStream would be better, but like I said the best solution would be FileWriter so that you can specify the charset to save in.
I am trying to create a program that uploads multiple files and stores their name and BPM tag into an ArrayList ready for comparison between the files. I have found two functions to help me but I am unable to combine them to get the function that I need.
The first function takes a singular mp3 file and outputs its data into the console (using mp3agic library):
File file = new File(dataPath("") + "/Song.mp3");
Mp3File mp3file = new Mp3File(file.getPath());
if (mp3file.hasId3v2Tag()) {
ID3v2 id3v2Tag = mp3file.getId3v2Tag();
println("Track: " + id3v2Tag.getTrack());
println("Artist: " + id3v2Tag.getArtist());
println("BPM: " + id3v2Tag.getBPM());
println("Album artist: " + id3v2Tag.getAlbumArtist());
}
The second function takes a data path and outputs the directory containing the names and info of the files in the folder
void setup() {
String path = "Desktop/mp3folder";
println("Listing all filenames in a directory: ");
String[] filenames = listFileNames(path);
printArray(filenames);
println("\nListing info about all files in a directory: ");
File[] files = listFiles(path);
for (int i = 0; i < files.length; i++) {
File f = files[i];
println("Name: " + f.getName());
println("Is directory: " + f.isDirectory())
println("-----------------------");
}
}
// This function returns all the files in a directory as an array of Strings
String[] listFileNames(String dir) {
File file = new File(dir);
if (file.isDirectory()) {
String names[] = file.list();
return names;
} else {
// If it's not a directory
return null;
}
}
// This function returns all the files in a directory as an array of File objects
// This is useful if you want more info about the file
File[] listFiles(String dir) {
File file = new File(dir);
if (file.isDirectory()) {
File[] files = file.listFiles();
return files;
} else {
// If it's not a directory
return null;
}
}
The function I am trying to create combines the two. I need the Artist, Track and BPM from the first function to work with an array list of files from a directory.
Any guidance would be appreciated. Any advice on another way to go about it would also be appreciated.
One way to approach this is to use classes to encapsulate the data you want to track.
For example, here's a simplified class that contains information about artist, track, and bpm:
public class TrackInfo{
private String artist;
private String track;
int bpm;
}
I would also take a step back, break your problem down into smaller steps, and then take those pieces on one at a time. Can you create a function that takes a File argument and prints out the MP3 data of that File?
void printMp3Info(File file){
// print out data about file
}
Get that working perfectly before moving on. Try calling it with hard-coded File instances before you try to use it with an ArrayList of multiple File instances.
Then if you get stuck, you can post a MCVE along with a specific technical question. Good luck.
I am attmpting to search through more then one text files in java for a matching random string ( given from the user ). I got myself a loop which loops throug filenames in the current directory in the project but i can't figure out how to open the files and check if i have a match somewhere int them. Here is the code that i have written to loop through the filenames.
String path = "."; //current directory
java.io.File folder = new java.io.File( path );
java.io.File[] fileList = folder.listFiles();
for( int i = 0; i < fileList.length; i++ ) {
// I should add code for searching int the files probably here
}
My research got me to some code for searching matches but in only one file and it looks like this:
final Scanner scanner = new Scanner(FileName);
while (scanner.hasNextLine()) {
final String lineFromFile = scanner.nextLine();
if(lineFromFile.contains("Address")) {
// a match!
System.out.println("I found " + CurrClient.getClientName()
+ " in file " +FileName+"txt");
break;
}
}
But it works only with one file or it seems to me like this.
Can you please give me a push? :)
Replace FileName with fileList[i] and your should be on your way.
By the way, you must remember to close the scanner in the end of each iteration of the loop, by calling scanner.close(). See more the examples in the documentation
I am trying to read 2 files after i read the files i want to get their contents and manipulate the contents of the two files then update a new file which is the output. The files are in the same folder as the program but the program always throws a FileNotFoundException.
Below is my code:-
import java.io.*;
import java.util.Scanner;
public class UpdateMaster {
public static void main(String[] args)
{
String master = "Customer.dat";
String trans = "Transactns.dat";
String newMaster = "Temp.txt";
Scanner inputStreamMaster = null;
Scanner inputStreamTrans = null;
PrintWriter inputStreamNewMaster = null;
try
{
inputStreamMaster = new Scanner(new File(master));
inputStreamTrans = new Scanner(new File(trans));
inputStreamNewMaster = new PrintWriter(newMaster);
}
catch(FileNotFoundException e)
{
System.out.println("Error: you opend a file that does not exist.");
System.exit(0);
}
catch(IOException e)
{
System.out.println("Error.");
System.exit(0);
}
do
{
String transLine = inputStreamTrans.nextLine();
String masterLine = inputStreamMaster.nextLine();
String[] transLineArr = transLine.split(",");
String[] masterLineArr = masterLine.split(",");
int trAccNo = Integer.parseInt(transLineArr[0]);
int sales = Integer.parseInt(transLineArr[1]);
int masterAccNo = Integer.parseInt(masterLineArr[0]);
int balance = Integer.parseInt(masterLineArr[1]);
while(masterAccNo== trAccNo){
inputStreamNewMaster.println(trAccNo+ " , "+masterAccNo);
masterLine = inputStreamMaster.nextLine();
masterLineArr = masterLine.split(",");
masterAccNo = Integer.parseInt(masterLineArr[0]);
balance = Integer.parseInt(masterLineArr[1]);
}
balance = balance + sales;
inputStreamNewMaster.println(masterAccNo+ " , "+balance);
}while(inputStreamTrans.hasNextLine());
inputStreamMaster.close();
inputStreamTrans.close();
inputStreamNewMaster.close();
//System.out.println(" the line were written to "+ newMaster);
}
}
Like #Ankit Rustagi said in the comments, you need the full path of the files if you want to keep the current implementation.
However, there is a solution where you only need the file names: use BufferedReader / BufferedWriter. See here an example on how to use these classes (in the example it uses the full path but it works without it too).
Use absolute path
String master = "C:/Data/Customer.dat";
String trans = "C:/Data/Transactns.dat";
String newMaster = "C:/Data/Temp.txt";
The code works for me, i guess you misspelled some filename(s) or your files are in the wrong folder. I created your files on the same level as the src or the project. Also this is the folder where the files are exspected.
There's nothing wrong with using relative paths like tihis. What's happening is that your program is looking for the files in the directory where you execute the program, which doesn't have to be the folder of the program. You can confirm this by logging the absolute path of the files before you try to read them. For example:
File masterFile = new File(master);
System.out.printf("Using master file '%s'%n", masterFile.getAbsolutePath());
inputStreamMaster = new Scanner(masterFile);
In general you should not hardcode file paths but allow the user to specify them in someway, for example using command line arguments, a configuration file with a well known path, or an interactive user interface.
There is a way to locate the program's class file but it's a little tricky because Java allows classes to be loaded from compressed archives that may be located in remote systems. It's better to solve this problem in some other manner.
Try this:
String current = new java.io.File( "." ).getCanonicalPath();
System.out.println("I look for files in:"+current);
To see what directory your program expects to find its input files. If it shows the correct directory, check spelling of filenames. Otherwise, you have a clue as to what's gone wrong.
I have a method for saving a File, but I don't know how to save files with consecutive names such as file001.txt, file002.txt, file003.txt, filennn.text
How can I achieve this?
You can use the following line of code to create the filenames.
String filename = String.format("file%03d.txt", fileNumber);
Then you will just use that string to create new files:
File file = new File(filename);
The following code will create files numbered 1 - 100:
for (int fileNumber = 1; fileNumber <= 100; fileNumber++) {
String filename = String.format("file%03d.txt", fileNumber);
File file = new File(filename);
}
Or, you will need to have a static variable that you increment every time you create a new file.
private static int fileNumber = 0;
public void createNewFile(){
String filename = String.format("file%03d.txt", fileNumber++);
File file = new File(filename);
}
It may be desirable for you to skip over writing to a file if it already exists.
This could be done easily by placing the following at the beginning of the for loop proposed by Justin 'jjnguy' Nelson, for example:
if(new File(fileName).exists())
{
continue;
}