I would expect exception to be thrown in this code at line: charSink.write("hi world"); since the file is set to be non writable. But this code executes without any exceptions. How to make CharSink respect file permissions?
public class CharSinkWritingNonWritableFile {
public static void main(String[] args) throws Exception {
final File file = getNewFile();
file.setWritable(false, false);
val charSink = Files.asCharSink(file, Charsets.UTF_8, FileWriteMode.APPEND);
file.setWritable(false, false);
charSink.write("hi world");
Files.readLines(file, Charsets.UTF_8).forEach(line -> {
System.out.println(line);
});
}
private static File getNewFile() {
final File file = new File("/tmp/hi-world");
if (file.exists()) {
file.delete();
}
return file;
}
}
Edit:
OS: MacOS 12.4
Related
public class TestResourceBundle {
private static final Path frZoo = Paths.get("./src/Zoo_fr.properties");
private static final Path enZoo = Paths.get("./src/Zoo_en.properties");
private static void createFiles() {
try {
Files.createFile(frZoo);
Files.createFile(enZoo);
try (BufferedWriter enWriter = Files.newBufferedWriter(enZoo);
BufferedWriter frWriter = Files.newBufferedWriter(frZoo);) {
enWriter.write("hello=Hello\nopen=The zoo is open");
frWriter.write("hello=Bonjour\nopen=Le zoo est ouvert");
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void createBundle() {
Locale us = new Locale("en", "US");
Locale france = new Locale("fr", "FR");
ResourceBundle usBundle = ResourceBundle.getBundle("Zoo", us);
ResourceBundle frBundle = ResourceBundle.getBundle("Zoo", france);
System.out.println(usBundle.getString("hello"));
System.out.println(frBundle.getString("hello"));
}
}
In the main function, if I run the following, it will throw java.util.MissingResourceException
public static void main(String[] args) {
createFiles();
createBundle();
}
but if I run these two functions separately (in two programs), it works and does not have any problem.
First run
public static void main(String[] args) {
createFiles();
// createBundle();
}
then run the following, in this case, it works
public static void main(String[] args) {
// createFiles();
createBundle();
}
I don't know why, please help
The problem is that you are trying to load a bundle that is not present in the classpath the application knows about.
When you call ResourceBundle.getBundle it will try to load the resource bundle from the application classpath. But the application classpath was already defined at the application startup, so your brand new files are not listed there.
Two options I can think of: Load the bundle from a file input stream or, define your own classloader to load the files.
1. Load the bundle from a File Input Stream
Create a new PropertyResourceBundle from a FileInputStream that loads each file directly.
Warning: Stream closing and exception handling omitted for brevity.
FileInputStream enFileStream = new FileInputStream("./src/Zoo_en.properties");
FileInputStream frFileStream = new FileInputStream("./src/Zoo_fr.properties");
ResourceBundle usBundle = new PropertyResourceBundle(enFileStream);
ResourceBundle frBundle = new PropertyResourceBundle(frFileStream);
2. Create a URL ClassLoader to load the new files
This is a more scalable approach. Create a new URLClassLoader and use that class loader as an argument for getBundle.
Warning: Stream closing and exception handling omitted for brevity.
File bundleRootPath = new File("./src");
URL[] urls = new URL[]{bundleRootPath.toURI().toURL()};
ClassLoader classLoader = new URLClassLoader(urls);
ResourceBundle usBundle = ResourceBundle.getBundle("Zoo", us, classLoader);
ResourceBundle frBundle = ResourceBundle.getBundle("Zoo", france, classLoader);
Hope that helps.
Trying to use java.util.logging and failing.
In an attempt to make use of https://stackoverflow.com/a/8249319/3322533 :
handlers = mypackage.logging.RequestFileHandler, mypackage.logging.MainFileHandler
config =
mainLogger.handlers = mypackage.logging.MainFileHandler
requestLogger.handlers = mypackage.logging.RequestFileHandler
java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.filter =
java.util.logging.ConsoleHandler.formatter = mypackage.logging.VerySimpleFormatter
java.util.logging.ConsoleHandler.encoding =
mypackage.RequestFileHandler.level = SEVERE
mypackage.RequestFileHandler.filter =
mypackage.RequestFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.RequestFileHandler.encoding =
mypackage.RequestFileHandler.limit =
mypackage.RequestFileHandler.count =
mypackage.RequestFileHandler.append = false
mypackage.RequestFileHandler.pattern = REQUESTS.%u.%g.log
mypackage.MainFileHandler.level = INFO
mypackage.MainFileHandler.filter =
mypackage.MainFileHandler.formatter = mypackage.logging.VerySimpleFormatter
mypackage.MainFileHandler.encoding =
mypackage.MainFileHandler.limit =
mypackage.MainFileHandler.count =
mypackage.MainFileHandler.append = false
mypackage.MainFileHandler.pattern = MAIN.%u.%g.log
where
public class MainFileHandler extends FileHandler {
public MainFileHandler() throws IOException, SecurityException {
super();
}
}
and
public class RequestFileHandler extends FileHandler {
public RequestFileHandler() throws IOException, SecurityException {
super();
}
}
Intention: provide two loggers accessible through
Logger.getLogger("mainLogger");
or
Logger.getLogger("requestLogger");
respectively, one that will write (exclusively) to MAIN[...].log and the other to REQUESTS[...].log
(No limits on the amount of messages that can be logged to either file and if necessary, use logging level to filter out unwanted msgs to either.)
However, neither file is created when I (for example)
public static final Logger log = Logger.getLogger("mainLogger");
and then
public void configureLogger(){
try {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
InputStream config = classLoader.getResourceAsStream("logging.properties");
LogManager.getLogManager().readConfiguration(config);
}catch(Exception ex){
throw new RuntimeException("logging properties failed");
}
}
before I
log.info("Hello World!")
I know the properties are loaded because when I include java.util.logging.ConsoleHandler in the handlers = ... list and use the global logger, instead, the formatter is applied for the console output.
So ... I guess my attempt at setting up the file loggers is faulty. How do I get this working?
EDIT
So I removed the [...].pattern = [...] lines and instead hardcoded the file names:
public class MainFileHandler extends FileHandler implements FileHandlerProperties {
public MainFileHandler() throws IOException, SecurityException {
super("MAIN_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
and
public class RequestFileHandler extends FileHandler implements FileHandlerProperties {
public RequestFileHandler() throws IOException, SecurityException {
super("REQUESTS_" + new SimpleDateFormat(TIME_PATTERN).format(new Date()) + ".log");
}
}
where
public interface FileHandlerProperties {
static final String TIME_PATTERN = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
}
Both files now get created BUT they both contain exactly the same (despite their different level settings and loggers) AND what they contain is in xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
<date>2016-10-10T18:49:23</date>
<millis>1476118163654</millis>
<sequence>0</sequence>
<logger>mainLogger</logger>
<level>INFO</level>
<class>mypackage.main.Main</class>
<method><init></method>
<thread>1</thread>
<message>Hello World</message>
</record>
</log>
Please help ...
The problem is that the first call to Logger.getLogger during class loading reads the log configuration and your configureLogger method fails due to JDK-8033661: readConfiguration does not cleanly reinitialize the logging system.
To workaround this you have to ensure that configureLogger runs before the first call to Logger.getLogger.
public class BootMain {
static {
configureLogger();
mainLogger = Logger.getLogger("mainLogger");
requestLogger = Logger.getLogger("requestLogger");
}
private static final Logger mainLogger;
private static final Logger requestLogger;
public static void main(String[] args) throws IOException {
mainLogger.log(Level.SEVERE, "Test from main.");
requestLogger.log(Level.SEVERE, "Test from request.");
System.out.println(new File(".").getCanonicalPath());
}
private static void configureLogger() {
try {
InputStream config = config();
LogManager.getLogManager().readConfiguration(config);
} catch (Exception ex) {
throw new RuntimeException("logging properties failed");
}
}
private static String prefix() {
return "mypackage.logging";
}
private static InputStream config() throws IOException {
String p = prefix();
Properties props = new Properties();
props.put("mainLogger.handlers", p + ".MainFileHandler");
props.put("requestLogger.handlers", p + ".RequestFileHandler");
props.put(p + ".RequestFileHandler.level", "SEVERE");
props.put(p + ".MainFileHandler.level", "INFO");
props.put(p + ".RequestFileHandler.pattern", "REQUESTS.%u.%g.log");
props.put(p + ".MainFileHandler.pattern", "MAIN.%u.%g.log");
ByteArrayOutputStream out = new ByteArrayOutputStream();
props.store(out, "");
return new ByteArrayInputStream(out.toByteArray());
}
}
Also make sure you are not using a really old version of JDK or you can run into JDK-5089480: java.util.logging.FileHandler uses hardcoded classname when reading properties.
Otherwise you can use the LogManager config option to manually setup your configuration.
The first time I save a file, even if it exists, I get the result I want. The file is overwritten. Now If I save again the text is appended to the file instead of overwriting. I have tried applying the approaches from similar questions I found answered here but none solve this. This is not answered by the possible duplicate. When I save a file the first time the behavior is what I want, the file is overwritten. However, all subsequent saves with the java window open append. That is incorrect. I suspect the file may not be closing after writing.
Edits:
This is a javafx package so the minimal amount of code to run is going to be a bit long but here it goes.
MainController:
public class MainController{
/** Holder of a switchable vista. */
#FXML public StackPane vistaHolder;
#FXML
public void programExit(){System.exit(0);}
public void permutationAnalyzer(){VistaNavigator.loadVista(VistaNavigator.VISTA_3);}
#FXML
public void saveFile() throws IOException {
OptionsDataCollector.generateOptionsFile();
}
public void setVista(Node node) {
vistaHolder.getChildren().setAll(node);
}
}
The data being saved:
public class OptionsDataCollector{
public static void generateOptionsFile() throws IOException {
StringBuilder moduleData = new StringBuilder();
moduleData.append("--target_perm_group_size\t").append(targetGroupSize).append("\n");
moduleData.append("--prog_check\t").append(progCheck).append("\n");
FileSaveUtility.fileSaveWindow(moduleData.toString());
//The next line is the answer.
moduleData.setLength(0);
}
}
FileSave:
public class FileSaveUtility {
private static void saveFile(String content, File file) throws IOException {
FileWriter fileWriter = new FileWriter(file.getAbsoluteFile(), false);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(content);
bufferedWriter.close();
//fileWriter.write(content);
//fileWriter.close();
}
public static void fileSaveWindow(String outFileData) throws IOException {
Stage primaryStage = new Stage();
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("TXT files (*.txt)", "*.txt");
fileChooser.getExtensionFilters().add(extFilter);
fileChooser.setInitialFileName("run_Volundr.txt");
File file = fileChooser.showSaveDialog(primaryStage);
if(file != null){
saveFile(outFileData, file);
//primaryStage.close();
}
}
}
I have not included the FXML files or the MainApp that generates it. I can add them if anyone wants. I have tried closing the stage, using StandardOpenOptions.Truncate_Exsisting and Files.deleteIfExsists. There is an object or stream not closing somewhere.
Frankly, I do not know even it is possible or not.
But what I am trying to do is just like below.
I made a class file from ClassFile.java via javac command in terminal.
Then I want to get an instance from .java file or .class file.
Next, I made another project in eclipse, As you guess this project path and upper file path are completely different. For instance, ClassFile.java/class file can be located in '~/Downloads' folder, the other hand, new eclipse project can be in '~/workspace/'.
So I read file which referred in step 1 by FileInputStream.
From here, I just paste my code.
public class Main {
private static final String CLASS_FILE_PATH =
"/Users/juneyoungoh/Downloads/ClassFile.class";
private static final String JAVA_FILE_PATH =
"/Users/juneyoungoh/Downloads/ClassFile.java";
private static Class getClassFromFile(File classFile) throws Exception {
System.out.println("get class from file : [" + classFile.getCanonicalPath() + " ]");
Object primativeClz = new Object();
ObjectInputStream ois = null;
ois = new ObjectInputStream(new FileInputStream(classFile));
primativeClz = ois.readObject();
ois.close();
return primativeClz.getClass();
}
public static void main(String[] args) throws Exception {
getClassInfo(getClassFromFile(new File(CLASS_FILE_PATH)));
}
}
just like your assumption, this code has errors.
For example, it shows :
java.io.StreamCurruptedException: invalid stream header : CAFEBABE
this there any way to get object instance from .class file or .java file?
P.S.
I wish do not use extra libraries.
private static final String CLASS_FOLDER =
"/Users/juneyoungoh/Downloads/";
private static Class getClassFromFile(String fullClassName) throws Exception {
URLClassLoader loader = new URLClassLoader(new URL[] {
new URL("file://" + CLASS_FOLDER)
});
return loader.loadClass(fullClassName);
}
public static void main( String[] args ) throws Exception {
System.out.println((getClassFromFile("ClassFile"));
}
My aim is to get list of all mp3 files in my computer(below code in c: directory). But when I run this code, I am getting NullPointerException. But works well for other directory like(e:).
public class music {
public static void main(String args[]){
extract("c:\\");
}
public static void extract(String p){
File f=new File(p);
File l[]=f.listFiles();
for(File x:l)
{
//System.out.println(x.getName());
if(x.isHidden()||!x.canRead())
continue;
if(x.isDirectory())
extract(x.getPath());
else if(x.getName().endsWith(".mp3"))
System.out.println(x.getPath()+"\\"+x.getName());
}
}
}
I got NPE with your code when it tried to access some not real directories like c:\Documents and Settings.
To solve this problem you can skip iterating over directories that returns null from listFiles() like in this code:
public static void main(String args[]) {
extract(new File("c:\\"));
}
public static void extract(File dir) {
File l[] = dir.listFiles();
if (l == null) {
System.out.println("[skipped] " + dir);
return;
}
for (File x : l) {
if (x.isDirectory())
extract(x);
if (x.isHidden() || !x.canRead())
continue;
else if (x.getName().endsWith(".mp3"))
System.out.println(x.getPath());//name should be included in path
}
}
In Windows operating system. C Drive (Windows drive) have system file that used by windows while running and some file that locked by windows. When your code try to access that files its through exception.
Try to run this code with other then C:// drive..
Add Try catch or null check for this files:
import java.io.*;
public class Music {
public static void main(String args[]){
extract("c:\\");
}
public static void extract(String p){
File f=new File(p);
File l[]=f.listFiles();
for(File x:l){
if(x==null) return;
if(x.isHidden()||!x.canRead()) continue;
if(x.isDirectory()) extract(x.getPath());
else if(x.getName().endsWith(".mp3"))
System.out.println(x.getPath()+"\\"+x.getName());
}
}
}