Setting file creation timestamp in Java - java

I know setting the creation timestamp doesn't exist in Java because Linux doesn't have it, but is there a way to set a file's (Windows) creation timestamp in Java? I have a basic modification timestamp editor I made right here.
import java.io.*;
import java.util.*;
import java.text.*;
import javax.swing.*;
public class chdt{
static File file;
static JFrame frame = new JFrame("Input a file to change");
public static void main(String[] args) {
try{
final JFileChooser fc = new JFileChooser();
fc.setMultiSelectionEnabled(false);
//BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
//System.out.println("Enter file name with extension:");
//String str = bf.readLine();
JOptionPane.showMessageDialog(null, "Input a file to change.");
frame.setSize(300, 200);
frame.setVisible(true);
int retVal = fc.showOpenDialog(frame);
if (retVal == JFileChooser.APPROVE_OPTION) {
file = fc.getSelectedFile();
frame.setVisible(false);
} else {
JOptionPane.showMessageDialog(null, "3RR0RZ! You didn't input a file.");
System.exit(0);
}
//System.out.println("Enter last modified date in 'dd-mm-yyyy-hh-mm-ss' format:");
//String strDate = bf.readLine();
String strDate = JOptionPane.showInputDialog("Enter last modified date in 'dd-mm-yyyy-hh-mm-ss' format:");
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss");
Date date = sdf.parse(strDate);
if (file.exists()){
file.setLastModified(date.getTime());
JOptionPane.showMessageDialog(null, "Modification is successful!");
}
else{
JOptionPane.showMessageDialog(null, "File does not exist! Did you accidentally it or what?");
}
}
catch(Exception e){
e.printStackTrace();
JOptionPane.showMessageDialog(null, "3RR0RZ");
}
}
}

Here is how you do it in Java 7 with the nio framework:
public void setFileCreationDate(String filePath, Date creationDate) throws IOException{
BasicFileAttributeView attributes = Files.getFileAttributeView(Paths.get(filePath), BasicFileAttributeView.class);
FileTime time = FileTime.fromMillis(creationDate.getTime());
attributes.setTimes(time, time, time);
}
the BasicFileAttributeView.setTimes(FileTime, FileTime, FileTime) method arguments set the last modified time, last accessed time, and creation time respectively.

Starting from Java 7, you can use java.nio.file.Files.setAttribute and the creationTime attribute:
Path p = Paths.get("C:\\Users\\first.last\\test.txt");
try {
Calendar c = Calendar.getInstance();
c.set(2010, Calendar.MARCH, 20);
Files.setAttribute(p, "creationTime", FileTime.fromMillis(c.getTimeInMillis()));
} catch (IOException e) {
System.err.println("Cannot change the creation time. " + e);
}
Other attributes can be found here:
Name Type
-------------------------------
"lastModifiedTime" FileTime
"lastAccessTime" FileTime
"creationTime" FileTime
"size" Long
"isRegularFile" Boolean
"isDirectory" Boolean
"isSymbolicLink" Boolean
"isOther" Boolean
"fileKey" Object

I believe you have the following options:
Find a tool that does this and is callable from the command line. Then you can interact with it from your java code.
The following link from MSDN File Times shows how any tool would be doing it - especially note the functions GetFileTime and SetFileTime.
And here I guess you will be lucky :) Searching for those functions on Google I found a post here on SO. This answer (not the accepted one) to How to Discover a File's Creation Time with Java seems to do exactly what you want using JNA and the methods above. And if it does, then please upvote that answer one more time :)
Please don't mind the title it has a method to set the creation time too. I hope you will manage to get it working.

You should search for java.nio if you are using jdk >= 1.7
You can also try this (worked well for me on Macos Mavericks and get me two different timestamps):
file.setLastModified(created.getTime()); //Older Timestamp
file.setLastModified(updated.getTime()); //Newer Timestamp

Related

Print log message in the same line [duplicate]

At the moment a default entry looks something like this:
Oct 12, 2008 9:45:18 AM myClassInfoHere
INFO: MyLogMessageHere
How do I get it to do this?
Oct 12, 2008 9:45:18 AM myClassInfoHere - INFO: MyLogMessageHere
Clarification I'm using java.util.logging
As of Java 7, java.util.logging.SimpleFormatter supports getting its format from a system property, so adding something like this to the JVM command line will cause it to print on one line:
-Djava.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'
Alternatively, you can also add this to your logger.properties:
java.util.logging.SimpleFormatter.format='%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$s %2$s %5$s%6$s%n'
Similar to Tervor, But I like to change the property on runtime.
Note that this need to be set before the first SimpleFormatter is created - as was written in the comments.
System.setProperty("java.util.logging.SimpleFormatter.format",
"%1$tF %1$tT %4$s %2$s %5$s%6$s%n");
1) -Djava.util.logging.SimpleFormatter.format
Java 7 supports a property with the java.util.Formatter format string syntax.
-Djava.util.logging.SimpleFormatter.format=...
See here.
My favorite is:
-Djava.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n
which makes output like:
2014-09-02 16:44:57 SEVERE org.jboss.windup.util.ZipUtil unzip: Failed to load: foo.zip
2) Putting it to IDEs
IDEs typically let you set system properties for a project.
E.g. in NetBeans, instead of adding -D...=... somewhere, add the property in the action dialog, in a form of java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-... - without any quotes. The IDE should figure out.
3) Putting that to Maven - Surefire
For your convenience, Here is how to put it to Surefire:
<!-- Surefire -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.17</version>
<configuration>
<systemPropertyVariables>
<!-- Set JUL Formatting -->
<java.util.logging.SimpleFormatter.format>%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS %4$-6s %2$s %5$s%6$s%n</java.util.logging.SimpleFormatter.format>
</systemPropertyVariables>
</configuration>
</plugin>
4) Hand-made
I have a library with few java.util.logging related classes. Amongst them, it's SingleLineFormatter.
Downloadable jar here.
public class SingleLineFormatter extends Formatter {
Date dat = new Date();
private final static String format = "{0,date} {0,time}";
private MessageFormat formatter;
private Object args[] = new Object[1];
// Line separator string. This is the value of the line.separator
// property at the moment that the SimpleFormatter was created.
//private String lineSeparator = (String) java.security.AccessController.doPrivileged(
// new sun.security.action.GetPropertyAction("line.separator"));
private String lineSeparator = "\n";
/**
* Format the given LogRecord.
* #param record the log record to be formatted.
* #return a formatted log record
*/
public synchronized String format(LogRecord record) {
StringBuilder sb = new StringBuilder();
// Minimize memory allocations here.
dat.setTime(record.getMillis());
args[0] = dat;
// Date and time
StringBuffer text = new StringBuffer();
if (formatter == null) {
formatter = new MessageFormat(format);
}
formatter.format(args, text, null);
sb.append(text);
sb.append(" ");
// Class name
if (record.getSourceClassName() != null) {
sb.append(record.getSourceClassName());
} else {
sb.append(record.getLoggerName());
}
// Method name
if (record.getSourceMethodName() != null) {
sb.append(" ");
sb.append(record.getSourceMethodName());
}
sb.append(" - "); // lineSeparator
String message = formatMessage(record);
// Level
sb.append(record.getLevel().getLocalizedName());
sb.append(": ");
// Indent - the more serious, the more indented.
//sb.append( String.format("% ""s") );
int iOffset = (1000 - record.getLevel().intValue()) / 100;
for( int i = 0; i < iOffset; i++ ){
sb.append(" ");
}
sb.append(message);
sb.append(lineSeparator);
if (record.getThrown() != null) {
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
sb.append(sw.toString());
} catch (Exception ex) {
}
}
return sb.toString();
}
}
Like Obediah Stane said, it's necessary to create your own format method. But I would change a few things:
Create a subclass directly derived from Formatter, not from SimpleFormatter. The SimpleFormatter has nothing to add anymore.
Be careful with creating a new Date object! You should make sure to represent the date of the LogRecord. When creating a new Date with the default constructor, it will represent the date and time the Formatter processes the LogRecord, not the date that the LogRecord was created.
The following class can be used as formatter in a Handler, which in turn can be added to the Logger. Note that it ignores all class and method information available in the LogRecord.
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
public final class LogFormatter extends Formatter {
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
#Override
public String format(LogRecord record) {
StringBuilder sb = new StringBuilder();
sb.append(new Date(record.getMillis()))
.append(" ")
.append(record.getLevel().getLocalizedName())
.append(": ")
.append(formatMessage(record))
.append(LINE_SEPARATOR);
if (record.getThrown() != null) {
try {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
record.getThrown().printStackTrace(pw);
pw.close();
sb.append(sw.toString());
} catch (Exception ex) {
// ignore
}
}
return sb.toString();
}
}
This is what I'm using.
public class VerySimpleFormatter extends Formatter {
private static final String PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
#Override
public String format(final LogRecord record) {
return String.format(
"%1$s %2$-7s %3$s\n",
new SimpleDateFormat(PATTERN).format(
new Date(record.getMillis())),
record.getLevel().getName(), formatMessage(record));
}
}
You'll get something like...
2016-08-19T17:43:14.295+09:00 INFO Hey~
2016-08-19T17:43:16.068+09:00 SEVERE Seriously?
2016-08-19T17:43:16.068+09:00 WARNING I'm warning you!!!
Per screenshot, in Eclipse select "run as" then "Run Configurations..." and add the answer from Trevor Robinson with double quotes instead of quotes. If you miss the double quotes you'll get "could not find or load main class" errors.
I've figured out a way that works. You can subclass SimpleFormatter and override the format method
public String format(LogRecord record) {
return new java.util.Date() + " " + record.getLevel() + " " + record.getMessage() + "\r\n";
}
A bit surprised at this API I would have thought that more functionality/flexibility would have been provided out of the box
If you log in a web application using tomcat add:
-Djava.util.logging.ConsoleHandler.formatter = org.apache.juli.OneLineFormatter
On VM arguments
This logging is specific to your application and not a general Java feature. What application(s) are you running?
It might be that this is coming from a specific logging library that you are using within your own code. If so, please post the details of which one you are using.
if you're using java.util.logging, then there is a configuration file that is doing this to log contents (unless you're using programmatic configuration). So, your options are
1) run post -processor that removes the line breaks
2) change the log configuration AND remove the line breaks from it. Restart your application (server) and you should be good.

try/catch failing incorrectly + console commands taking input but not running

So I'm currently taking AP Comp Sci A and am trying to learn Java, and while developing a small program to keep up with my teacher I've run into a couple issues.
The program is intended to take entries and log them in a journal. I'd eventually like to have it stored in an HTML format and then be able to email my logs to a teacher in an HTML table, but this issue is preventing that.
Basically, with my catch, I'm trying to create and then enter starting HTML code (,, and then necessary tags for the html table) but even if the file doesn't exist the catch isn't running correctly, presumably because of the 'throws IOException' Exclipse had me add.
I also attempted to add commands to my program, but nothing happens when used. No exceptions thrown, nothing printed, etc.
Here's my code:
import java.util.Scanner;
import java.util.Calendar;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LogSend {
/**
* #param args
* #throws IOException
*/
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
System.out.println("");
System.out.println("Type '!help' for commands");
Scanner cmd = new Scanner(System.in);
String initialCmd = cmd.nextLine();
if (initialCmd == "!help") {
System.out.println("The commands are:");
System.out.println("'!help' for commands");
System.out.println("'!log' to log an entry");
} else if (initialCmd == "!log") {
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
System.out.println(timeStamp);
Scanner entry = new Scanner(System.in);
String journalEntry = entry.nextLine();
try (PrintWriter saveLog = new PrintWriter(new FileWriter("log.html", true))) {
saveLog.println(timeStamp+":"+"<b>"+journalEntry+"</b>"+"<br>");
}
}
/*String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(Calendar.getInstance().getTime());
System.out.println(timeStamp);
Scanner entry = new Scanner(System.in);
String journalEntry = entry.nextLine();
try (PrintWriter saveLog = new PrintWriter(new FileWriter("log.html", true))) {
saveLog.println(timeStamp+":"+"<b>"+journalEntry+"</b>"+"<br>");
} /*catch(FileNotFoundException e) {
FileWriter fileWriter = new FileWriter("log.html");
PrintWriter saveLog = new PrintWriter(fileWriter);
saveLog.println("<html>");
saveLog.println("<body>");
saveLog.println(timeStamp+":"+journalEntry);
saveLog.println("</body>");
saveLog.println("</html>");
}*/
}
}
Sorry if this is all a bit stupid, I'm brand new to Java and find I learn best through just making programs. I appreciate the help.
NOTE: It's worth noting I've commented out the catch because it's simply not working, but that's the code I used.
First String comparison goes by a method equals
initialCmd == "!help"
initialCmd.equals("!help") // Or equalsIgnoreCase
Then
try (PrintWriter saveLog = new PrintWriter(new FileWriter("log.html", true))) {
saveLog.println(timeStamp+":"+"<b>"+journalEntry+"</b>"+"<br>");
}
is okay, as it writes to the file in append mode (the true) and will almost never throw a FileNotFoundException (=could not create file).
You may do:
try (...
...
} catch (IOException e) {
e.printStackTrace();
}
As FileNotFoundException is also an IOException. For out-of-diskspace, missing rights, wrong directory path.
One remark: FileWriter will use the default (=platform) encoding. For
the full Unicode range that a String is capable of, you could use UTF-8:
try (PrintWriter saveLog = new PrintWriter(
Files.newBufferedWriter(Paths.get("log.html"),
StandardCharsets.UTF_8,
StandardOpenOption.APPEND,
StandardOpenOption.CREATE))) {
saveLog.printf("%s:<b>%s</b><br>%n", timeStamp, journalEntry);
}
Also not that one cause for an exception might be two thread logging to the file.
It would not be wrong to invest time in the java.util.logging framework that can be customized to about the same functionality, and more.
The above does not throw a catch on a non-existing file, assuming the same content being written.
For HTML one would like to write a beginning. One can do that by including the log file in a real HTML file:
<!DOCTYPE html [
<ENTITY log SYSTEM "log.html">
]>
<html>
<head>
<title>Logs</title>
<meta charset="UTF-8">
<meta http-equiv="refresh" content="5"> <!-- reload every 5s -->
</head>
<body>
&log;
</body>
</html>
#index.php For clarification, passing true as the 2nd argument of FileWriter (as #JoopEggen suggests) causes the file to be created if it doesn't exist and to be opened for appending if it does exist. Therefore you won't hit the catch as you'll create a new file logs.html and append to it once created. Isn't that what you're trying to do anyway? So if the catch is just for creating the file when it doesn't exist, it is no longer required?
On the other hand, if you're trying to log the fact the file never existed you can use java.io.File and do something like:
File f = new File(filePathString);
//Note we do !f.isDirectory() as exists will return true for directories too
if(f.exists() && !f.isDirectory()) {
// log that file didn't exist
// create file and append custom error
}
Though with this method you need to be careful not to run into race conditions.
Hope this helps, let me know how you get on!

Need help creating a program to read in entries and replace existing entry if there is one for that date

I am very new to coding and learning java, I can picture what the program needs to do however implementing to code has proven tough for me. I am trying to create a constructor. The constructor needs to do the following-
Constructor: When reading in and storing the individual quiz data, you will need to watch out for repeated quizzes. If a quiz is read in with a date that already has an entry stored, you will need to replace the earlier entry with the new one. I have been provided a java doc for this, however I will need to create the code. I have attached an image of the javadoc as well as the code that I currently have.
Javadoc for Constructor
public QuizList(String filename)
{
this.quizzesList = 0;
this.quizList = new ArrayList<Quiz>();
try {
Scanner infile = new Scanner(new File(filename));
while (infile.hasNextLine()){
String quizDate = infile.next();
String pointsEarned = infile.next();
String possiblePoints = infile.nextLine().trim();
Quiz quiz = new Quiz(quizDate, points, possible);
this.quizzes.add(quiz);
}
infile.close();
}
catch (java.io.FileNotFoundException e) {
System.out.println("No such file: " + filename);
}
File has lastModified method: https://docs.oracle.com/javase/8/docs/api/java/io/File.html.
I recommend you to iterate the files on the directory and check their last modified date.

Java: Writing string to .txt issue

Here is the longish, but commented code for my program:
public static void main(String args[])
{
//get path of dump file
Path directory = Paths.get("E:\\Temp\\");
try
{
Files.createDirectory(directory);
}
catch(FileAlreadyExistsException e)
{
System.err.println("Directory already exists.");
}
catch(IOException e)
{
System.err.println("Could not create directory.");
e.printStackTrace();
System.exit(1);
}
Path file = directory.resolve("dump.txt");
//set initial vars and get system properties
long gig = 1_073_741_824L;
String separator = System.lineSeparator();
FileSystem fs = FileSystems.getDefault();
Iterable<FileStore> fstores = fs.getFileStores();
//write data to file
try(WritableByteChannel wbc = Files.newByteChannel(file, CREATE, WRITE,TRUNCATE_EXISTING))
{
//write heading to file
ByteBuffer buf_1 = ByteBuffer.wrap(new String("*****FILE SYSTEM DATA*****" + separator + separator).getBytes());
wbc.write(buf_1);
//write file store information to file
for(FileStore store : fstores)
{
//set up empty string and formatter for it
String f_string = "";
Formatter f = new Formatter(f_string);
//fill f_string
f.format("\nStore: %-20s Format: %-5s Capacity: %5dGB Unallocated: %5dGB",
store.name(),
store.type(),
store.getTotalSpace()/gig,
store.getUnallocatedSpace()/gig);
//test
System.out.println(f_string);
//set up buffers
ByteBuffer buf = ByteBuffer.wrap(f_string.getBytes());
//write to file
wbc.write(buf);
f.close();
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
The purpose of this program is to create a .txt file called "dump.txt" at a (currently) hard-coded location on my system containing information about my file system. The problem that I am having is that nothing is written to the file other than the title "*****FILE SYSTEM DATA*****", and in fact when I debug the code, every line between creating the Formatter and the final catch block does not get stepped through. The way in which I attempt to write this data to the file is the same as how I write buf_1 (heading) to the file, and so I am completely at a loss as to why this problem is occurring.
Any advice would be greatly appreciated.
P.S. I have thought about using a Writer instead, but for the sake of my own knowledge I am using channel/buffer objects instead. However, if you know some particular reason why a Writer would be superior, please let me know :).
You are not assigning the formatted string to f_string before writing it to the file.
Instead of
String f_string = "";
Formatter f = new Formatter(f_string);
f.format("\nStore: %-20s Format: %-5s Capacity: %5dGB Unallocated: %5dGB",
store.name(),
store.type(),
store.getTotalSpace()/gig,
store.getUnallocatedSpace()/gig);;
You should have something like:
Formatter f = new Formatter(f_string);
String f_string =
f.format("\nStore: %-20s Format: %-5s Capacity: %5dGB Unallocated: %5dGB",
store.name(),
store.type(),
store.getTotalSpace()/gig,
store.getUnallocatedSpace()/gig);;
Formatter does not work like you think it does, but you don't actually need to use it anyway. Use String.format instead:
String f_string = String.format("\nStore: %-20s Format: %-5s Capacity: %5dGB Unallocated: %5dGB",
store.name(),
store.type(),
store.getTotalSpace()/gig,
store.getUnallocatedSpace()/gig);

What is the best way to generate a unique and short file name in Java

I don't necessarily want to use UUIDs since they are fairly long.
The file just needs to be unique within its directory.
One thought which comes to mind is to use File.createTempFile(String prefix, String suffix), but that seems wrong because the file is not temporary.
The case of two files created in the same millisecond needs to be handled.
Well, you could use the 3-argument version: File.createTempFile(String prefix, String suffix, File directory) which will let you put it where you'd like. Unless you tell it to, Java won't treat it differently than any other file. The only drawback is that the filename is guaranteed to be at least 8 characters long (minimum of 3 characters for the prefix, plus 5 or more characters generated by the function).
If that's too long for you, I suppose you could always just start with the filename "a", and loop through "b", "c", etc until you find one that doesn't already exist.
I'd use Apache Commons Lang library (http://commons.apache.org/lang).
There is a class org.apache.commons.lang.RandomStringUtils that can be used to generate random strings of given length. Very handy not only for filename generation!
Here is the example:
String ext = "dat";
File dir = new File("/home/pregzt");
String name = String.format("%s.%s", RandomStringUtils.randomAlphanumeric(8), ext);
File file = new File(dir, name);
I use the timestamp
i.e
new File( simpleDateFormat.format( new Date() ) );
And have the simpleDateFormat initialized to something like as:
new SimpleDateFormat("File-ddMMyy-hhmmss.SSS.txt");
EDIT
What about
new File(String.format("%s.%s", sdf.format( new Date() ),
random.nextInt(9)));
Unless the number of files created in the same second is too high.
If that's the case and the name doesn't matters
new File( "file."+count++ );
:P
This works for me:
String generateUniqueFileName() {
String filename = "";
long millis = System.currentTimeMillis();
String datetime = new Date().toGMTString();
datetime = datetime.replace(" ", "");
datetime = datetime.replace(":", "");
String rndchars = RandomStringUtils.randomAlphanumeric(16);
filename = rndchars + "_" + datetime + "_" + millis;
return filename;
}
// USE:
String newFile;
do{
newFile=generateUniqueFileName() + "." + FileExt;
}
while(new File(basePath+newFile).exists());
Output filenames should look like :
2OoBwH8OwYGKW2QE_4Sep2013061732GMT_1378275452253.Ext
Look at the File javadoc, the method createNewFile will create the file only if it doesn't exist, and will return a boolean to say if the file was created.
You may also use the exists() method:
int i = 0;
String filename = Integer.toString(i);
File f = new File(filename);
while (f.exists()) {
i++;
filename = Integer.toString(i);
f = new File(filename);
}
f.createNewFile();
System.out.println("File in use: " + f);
If you have access to a database, you can create and use a sequence in the file name.
select mySequence.nextval from dual;
It will be guaranteed to be unique and shouldn't get too large (unless you are pumping out a ton of files).
//Generating Unique File Name
public String getFileName() {
String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
return "PNG_" + timeStamp + "_.png";
}
I use current milliseconds with random numbers
i.e
Random random=new Random();
String ext = ".jpeg";
File dir = new File("/home/pregzt");
String name = String.format("%s%s",System.currentTimeMillis(),random.nextInt(100000)+ext);
File file = new File(dir, name);
Combining other answers, why not use the ms timestamp with a random value appended; repeat until no conflict, which in practice will be almost never.
For example: File-ccyymmdd-hhmmss-mmm-rrrrrr.txt
Why not just use something based on a timestamp..?
Problem is synchronization. Separate out regions of conflict.
Name the file as : (server-name)_(thread/process-name)_(millisecond/timestamp).(extension)
example : aws1_t1_1447402821007.png
How about generate based on time stamp rounded to the nearest millisecond, or whatever accuracy you need... then use a lock to synchronize access to the function.
If you store the last generated file name, you can append sequential letters or further digits to it as needed to make it unique.
Or if you'd rather do it without locks, use a time step plus a thread ID, and make sure that the function takes longer than a millisecond, or waits so that it does.
It looks like you've got a handful of solutions for creating a unique filename, so I'll leave that alone. I would test the filename this way:
String filePath;
boolean fileNotFound = true;
while (fileNotFound) {
String testPath = generateFilename();
try {
RandomAccessFile f = new RandomAccessFile(
new File(testPath), "r");
} catch (Exception e) {
// exception thrown by RandomAccessFile if
// testPath doesn't exist (ie: it can't be read)
filePath = testPath;
fileNotFound = false;
}
}
//now create your file with filePath
This also works
String logFileName = new SimpleDateFormat("yyyyMMddHHmm'.txt'").format(new Date());
logFileName = "loggerFile_" + logFileName;
I understand that I am too late to reply on this question. But I think I should put this as it seems something different from other solution.
We can concatenate threadname and current timeStamp as file name. But with this there is one issue like some thread name contains special character like "\" which can create problem in creating file name. So we can remove special charater from thread name and then concatenate thread name and time stamp
fileName = threadName(after removing special charater) + currentTimeStamp
Why not use synchronized to process multi thread.
here is my solution,It's can generate a short file name , and it's unique.
private static synchronized String generateFileName(){
String name = make(index);
index ++;
return name;
}
private static String make(int index) {
if(index == 0) return "";
return String.valueOf(chars[index % chars.length]) + make(index / chars.length);
}
private static int index = 1;
private static char[] chars = {'a','b','c','d','e','f','g',
'h','i','j','k','l','m','n',
'o','p','q','r','s','t',
'u','v','w','x','y','z'};
blew is main function for test , It's work.
public static void main(String[] args) {
List<String> names = new ArrayList<>();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 100; i++) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
for (int i = 0; i < 1000; i++) {
String name = generateFileName();
names.add(name);
}
}
});
thread.run();
threads.add(thread);
}
for (int i = 0; i < 10; i++) {
try {
threads.get(i).join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(names);
System.out.println(names.size());
}

Categories