How to Write/ Edit a txt file using Kotlin in Android Studio? - java

I am in the beginning of Android App learning phase. I have a .txt file in my assets folder consisting of strings in each line, like this-
AWOL JJ AWOL
Aaronic JJ Aaronic
Aaronical JJ Aaronical
What I want to do is just replace JJ with NN and keep rest the same. My questions are-
Is there a way to edit the already existing file, because all the solutions I found are talking about creating some other file using function File(<filename>)?
If I follow the solutions described on different websites, I can not access the file USING File(), it shows the error that the file can not be found even though I have created an empty file with the same name. I can not access the file if it is inside assets folder or inside app/src. So, instead I am using Context.assets.open(<filename>) for readin the orginal file which opens the file as inputstream. Although I don't know any other way of opening the file using File() for writing.
// FOR READING FROM ORIGINAL FILE
var inputStreamLemmDict = BufferedReader(InputStreamReader(context!!.assets.open("my_file.dict"))).readLines()
// FOR WRITING TO ANOTHER FILE
File("path_to/my_file.txt").bufferedWriter().use { out ->
inputStreamLemmDict.forEach {
var eachLineSplit = it.split("\\s".toRegex())
if (eachLineSplit[1] == "NNN") {
out.write("${eachLineSplit[0]}\tNN\t${eachLineSplit[2]}\n")
}
else {
out.write("${it}\n")
}
}
Any help is appreciated. Thank you!

Hi you can use the following solution to achieve your desired result.
UPDATE : Please try this solution to read file from assets and get your result. This solution is not tested.
Make sure yourfilename.txt is under assets folder.
try {
val inputStream:InputStream = assets.open("yourfilename.txt")
val text = inputStream.bufferedReader().use{it.readText()}
println(text)
text = text.replace("JJ".toRegex(), "NN")
f.writeText(text)
}catch (e:Exception){
Log.d(TAG, e.toString())
}

fun main(args: Array<String>) {
var lineNumber = 0
var newString = ""
File("src/dataFile").forEachLine {
++lineNumber
println("$lineNumber: $it")
newString = it.replace("JJ", "NN")
println("New string : $newString")
}
File("src/dataFile").writeText(newString)
}

Related

Does System.IO.File encapsulates SMB1.0/SMB2.0?

I am new to SMB1.0/SMB2.0 and am trying to create a C# class library to encapsulate basic File/Directory operations like Copy, ReadAllText, Delete, etc., using https://github.com/TalAloni/SMBLibrary.
My questions are:
Is System.IO.File already encapsulate SMB1.0/SMB2.0 protocol, and do I not need to use 3rd party SMBLibrary?
I have written the following code to Move a file from one SMB share to another SMB share, but it only renames and does not Move the file from a source location to the target location. How can I do that?
public bool Move(string sourceFilePath, string targetFilePath)
{
if (!CheckLoggedIn())
{
return false;
}
object fileHandle = null;
_status = _store.CreateFile(out fileHandle,
out FileStatus _,
sourceFilePath,
AccessMask.GENERIC_ALL | AccessMask.SYNCHRONIZE,
FileAttributes.Normal,
ShareAccess.Write,
CreateDisposition.FILE_OPEN,
CreateOptions.FILE_NON_DIRECTORY_FILE | CreateOptions.FILE_SYNCHRONOUS_IO_ALERT,
null);
if (_status == NTStatus.STATUS_SUCCESS)
{
_status = _store.SetFileInformation(fileHandle, new FileRenameInformationType2()
{
FileName = targetFilePath
});
_status = _store.CloseFile(fileHandle);
}
return _status == NTStatus.STATUS_SUCCESS;
}
No, System.IO does not contain an SMB 1.0 or SMB 2.0 client.
In order to move file from one share to another, the client must read the content of the file from the source share, and then write its content to the second share. it must be copied in this manner (and then deleted from the source).
I found EzSmb https://github.com/ume05rw/EzSmb library with which you could move files within same SMB share using the following code:
// ** SMB1 NOT Supported. **
//using EzSmb;
//using System;
//using System.Threading.Tasks;
// Get Node of file.
var file = await Node.GetNode(#"192.168.0.1\ShareName\FileName.txt", "userName", "password");
// Move to child folder path.
// ** Even if you don't change the file/folder name, write the name. **
var movedFile = await file.Move(#"FolderName\RenamedFileName.txt");
Console.WriteLine(movedFile.FullPath);
// -> 192.168.0.1\ShareName\FolderName\RenamedFileName.txt
// Get Node of folder.
var folder = await Node.GetNode(#"192.168.0.1\ShareName\FolderName\SubFolderName", "userName", "password");
// Move to Parent path.
var movedFolder = await folder.Move(#"..\RenamedSubFolderName");
Console.WriteLine(movedFolder.FullPath);
// -> 192.168.0.1\ShareName\RenamedSubFolderName

Domino app - how to access the source document in java during custom file attachment routine

This is a non-xpages application.
I have inherited some code that I need to tweak....this code is used in a drag&drop file attachment subform. Normally, this will create a document in a separate dedicated .nsf that stores only attachments, and uses the main document's universalid as a reference to link the two....I need to change what the reference is to the value in a field already on the main document (where the subform is).
Java is challenging to me, but all I need to do is GET the value of the field from the main document (which has not necessarily been saved yet) and write that string value onto the attachment doc in that storage database, so I think I am just needing help with one line of code.
I will paste the relevant function here and hopefully someone can tell me how I get that value, or what else they need to see what is going on here.
You can see my commented-out attempt to write the field 'parentRef' in this code
...
private void storeUploadedFile( UploadedFile uploadedFile, Database dbTarget) {
File correctedFile = null;
RichTextItem rtFiles = null;
Document doc = null;
String ITEM_NAME_FILES = "file";
try {
if (uploadedFile==null) {
return;
}
doc = dbTarget.createDocument();
doc.replaceItemValue("form", "frmFileUpload");
doc.replaceItemValue("uploadedBy", dbTarget.getParent().getEffectiveUserName() );
Utils.setDate(doc, "uploadedAt", new Date() );
doc.replaceItemValue("parentUnid", parentUnid);
//doc.replaceItemValue("parentRef", ((Document) dbTarget.getParent()).getItemValue("attachmentDocKey"));
//get uploaded file and attach it to the document
fileName = uploadedFile.getClientFileName();
File tempFile = uploadedFile.getServerFile(); //the uploaded file with a cryptic name
fileSize = tempFile.length();
targetUnid = doc.getUniversalID();
correctedFile = new java.io.File( tempFile.getParentFile().getAbsolutePath() + java.io.File.separator + fileName );
//rename the file on the OS so we can embed it with the correct (original) name
boolean success = tempFile.renameTo(correctedFile);
if (success) {
//embed original file in target document
rtFiles = doc.createRichTextItem(ITEM_NAME_FILES);
rtFiles.embedObject(lotus.domino.EmbeddedObject.EMBED_ATTACHMENT, "", correctedFile.getAbsolutePath(), null);
success = doc.save();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
com.gadjj.Utils.recycle(rtFiles, doc);
try {
if (correctedFile != null) {
//rename the temporary file back to its original name so it's automatically
//removed from the os' file system.
correctedFile.renameTo(uploadedFile.getServerFile());
}
} catch(Exception ee) { ee.printStackTrace(); }
}
}
}
...
dbTarget.getParent does not do what you think it does. It returns a Session object that is the parent session containing all your objects. Casting it to (Document) won't give you your main document.
I don't see the declaration for it, but you appear to have a variable available called parentUNID. You can use it to get a handle on the main document.
You need to use the parentUNID value in a call to getDocumentByUNID() in order to retrieve the Document object representing your main document. But in order to do that, you need the Database object for the nsf file containing the main document, and if I understand you correctly, that is a different database than targetDb.
I'm going to have to assume that you already have that Database object in a variable called parentDb, or that you know the path to the NSF and can open it. In either case, your code would look like this (without error handling):
Document parentDoc = parentDb.getDocumentByUNID(parentUNID);
doc.replaceItemvalue("parentRef", parentDoc.getItemValue("attachmentDocKey"));

Change id3 tag version programatically (pref java)

I need a way to change id3 tag version of mp3 files to some id3v2.x programatically, preferably using java though anything that works is better than nothing. Bonus points if it converts the existing tag so that already existing data isn't destroyed, rather than creating a new tag entirely.
Edit: Jaudiotagger worked, thanks. Sadly I had to restrict it to mp3 files and only saving data contained in previous tags if they were id3. I decided to convert the tag to ID3v2.3 since windows explorer can't handle v2.4, and it was a bit tricky since the program was a bit confused about whether to use the copy constructor or the conversion constructor.
MP3File mf = null;
try {
mf = (MP3File)AudioFileIO.read(new File(pathToMp3File));
} catch (Exception e) {}
ID3v23Tag tag;
if (mf.hasID3v2Tag()) tag = new ID3v23Tag(mf.getID3v2TagAsv24());
else if (mf.hasID3v1Tag()) tag = new ID3v23Tag(mf.getID3v1Tag());
else tag = new ID3v23Tag();
My application must be able to read id3v1 or id3v11, but shall only write v23, so I needed a little bit longer piece of code:
AudioFile mf;
Tag mTagsInFile;
...
mf = ... // open audio file the usual way
...
mTagsInFile = mf.getTag();
if (mTagsInFile == null)
{
//contrary to getTag(), getTagOrCreateAndSetDefault() ignores id3v1 tags
mTagsInFile = mf.getTagOrCreateAndSetDefault();
}
// mp3 id3v1 and id3v11 are suboptimal, convert to id3v23
if (mf instanceof MP3File)
{
MP3File mf3 = (MP3File) mf;
if (mf3.hasID3v1Tag() && !mf3.hasID3v2Tag())
{
// convert ID3v1 tag to ID3v23
mTagsInFile = new ID3v23Tag(mf3.getID3v1Tag());
mf3.setID3v1Tag(null); // remove v1 tags
mf3.setTag(mTagsInFile); // add v2 tags
}
}
Basically we have to know that getTagOrCreateAndSetDefault() and similar unfortunately ignores id3v1, so we first have to call getTag(), and only if this fails, we call the mentioned function.
Additionally, the code must also deal with flac and mp4, so we make sure to do our conversion only with mp3 files.
Finally there is a bug in JaudioTagger. You may replace this line
String genre = "(" + genreId + ") " + GenreTypes.getInstanceOf().getValueForId(genreId);
in "ID3v24Tag.java" with this one
String genre = GenreTypes.getInstanceOf().getValueForId(genreId);
Otherwise genre 12 from idv1 will get "(12) Other" which later is converted to "Other Other" and this is not what we would expect. Maybe someone has a more elegant solution.
You can use different libraries for this purpose, for example this or this.

Textscreen in Codename One, how to read text file?

I want to add a help screen to my Codename One App.
As the text is longer as other strings, I would like put it in a separate file and add it to the app-package.
How do I do this? Where do I put the text file, and how can I easily read it in one go into a string?
(I already know how to put the string into a text area inside a form)
In the Codename One Designer go to the data section and add a file.
You can just add the text there and fetch it using myResFile.getData("name");.
You can also store the file within the src directory and get it using Display.getInstance().getResourceAsStream("/filename.txt");
I prefer to have the text file in the filesystem instead of the resource editor, because I can just edit the text with the IDE. The method getResourceAsStream is the first part of the solution. The second part is to load the text in one go. There was no support for this in J2ME, you needed to read, handle buffers etc. yourself. Fortunately there is a utility method in codename one. So my working method now looks like this:
final String HelpTextFile = "/helptext.txt";
...
InputStream in = Display.getInstance().getResourceAsStream(
Form.class, HelpTextFile);
if (in != null){
try {
text = com.codename1.io.Util.readToString(in);
in.close();
} catch (IOException ex) {
System.out.println(ex);
text = "Read Error";
}
}
The following code worked for me.
//Gets a file system storage instance
FileSystemStorage inst = FileSystemStorage.getInstance();
//Gets CN1 home`
final String homePath = inst.getAppHomePath();
final char sep = inst.getFileSystemSeparator();
// Getting input stream of the file
InputStream is = inst.openInputStream(homePath + sep + "MyText.txt");
// CN1 Util class, readInputStream() returns byte array
byte[] b = Util.readInputStream(is);
String myString = new String(b);

Writing in the beginning of a text file Java

I need to write something into a text file's beginning. I have a text file with content and i want write something before this content. Say i have;
Good afternoon sir,how are you today?
I'm fine,how are you?
Thanks for asking,I'm great
After modifying,I want it to be like this:
Page 1-Scene 59
25.05.2011
Good afternoon sir,how are you today?
I'm fine,how are you?
Thanks for asking,I'm great
Just made up the content :) How can i modify a text file like this way?
You can't really modify it that way - file systems don't generally let you insert data in arbitrary locations - but you can:
Create a new file
Write the prefix to it
Copy the data from the old file to the new file
Move the old file to a backup location
Move the new file to the old file's location
Optionally delete the old backup file
Just in case it will be useful for someone here is full source code of method to prepend lines to a file using Apache Commons IO library. The code does not read whole file into memory, so will work on files of any size.
public static void prependPrefix(File input, String prefix) throws IOException {
LineIterator li = FileUtils.lineIterator(input);
File tempFile = File.createTempFile("prependPrefix", ".tmp");
BufferedWriter w = new BufferedWriter(new FileWriter(tempFile));
try {
w.write(prefix);
while (li.hasNext()) {
w.write(li.next());
w.write("\n");
}
} finally {
IOUtils.closeQuietly(w);
LineIterator.closeQuietly(li);
}
FileUtils.deleteQuietly(input);
FileUtils.moveFile(tempFile, input);
}
I think what you want is random access. Check out the related java tutorial. However, I don't believe you can just insert data at an arbitrary point in the file; If I recall correctly, you'd only overwrite the data. If you wanted to insert, you'd have to have your code
copy a block,
overwrite with your new stuff,
copy the next block,
overwrite with the previously copied block,
return to 3 until no more blocks
As #atk suggested, java.nio.channels.SeekableByteChannel is a good interface. But it is available from 1.7 only.
Update : If you have no issue using FileUtils then use
String fileString = FileUtils.readFileToString(file);
This isn't a direct answer to the question, but often files are accessed via InputStreams. If this is your use case, then you can chain input streams via SequenceInputStream to achieve the same result. E.g.
InputStream inputStream = new SequenceInputStream(new ByteArrayInputStream("my line\n".getBytes()), new FileInputStream(new File("myfile.txt")));
I will leave it here just in case anyone need
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (FileInputStream fileInputStream1 = new FileInputStream(fileName1);
FileInputStream fileInputStream2 = new FileInputStream(fileName2)) {
while (fileInputStream2.available() > 0) {
byteArrayOutputStream.write(fileInputStream2.read());
}
while (fileInputStream1.available() > 0) {
byteArrayOutputStream.write(fileInputStream1.read());
}
}
try (FileOutputStream fileOutputStream = new FileOutputStream(fileName1)) {
byteArrayOutputStream.writeTo(fileOutputStream);
}

Categories