Replacement of text in xml file by AHK - get error when trying to open as xml file - autohotkey

I am using an AHK script to replace some text in an .xml file (Result.xml in this case). The script then saves a file as Result_copy.xml. It changes exactly what I need, but when I try to open the new xml file, it won't open, giving me the error:
This page contains the following errors:
error on line 4 at column 16: Encoding error
Below is a rendering of the page up to the first error.
I only replaced text at line 38 using:
#Include TF.ahk
path = %1%
text = %2%
TF_ReplaceLine(path, 38, 38, text)
%1% and %2% are given by another program and are working as should
I also see that the orginal Result.xml is 123 kb and Result_copy.xml is 62 kb, even though I only add text. When I take Result.xml and manually add the text and save it, it's 123 kb and still opens. so now both files contain exactly the same Characters, but one won't open as xml. I think that something happens during saving/copying, which I don't understand.
Could someone help me out on this one? I don't have a lot of experience in AHK scripting and do not have a programming background.
Thank you in advance!
Michel
TF.ahk contains this:
/*
Name : TF: Textfile & String Library for AutoHotkey
Version : 3.8
Documentation : https://github.com/hi5/TF
AutoHotkey.com: https://www.autohotkey.com/boards/viewtopic.php?f=6&t=576
AutoHotkey.com: http://www.autohotkey.com/forum/topic46195.html (Also for examples)
License : see license.txt (GPL 2.0)
Credits & History: See documentation at GH above.
TF_ReplaceLine(Text, StartLine = 1, Endline = 0, ReplaceText = "")
{
TF_GetData(OW, Text, FileName)
TF_MatchList:=_MakeMatchList(Text, StartLine, EndLine, 0, A_ThisFunc) ; create MatchList
Loop, Parse, Text, `n, `r
{
If A_Index in %TF_MatchList%
Output .= ReplaceText "`n"
Else
Output .= A_LoopField "`n"
}
Return TF_ReturnOutPut(OW, OutPut, FileName)
}

Related

Autohotkey - how to store unicode and use it?

Here's my code below. AHK file is saved as UTF-8 with BOM and I can see the unicode characters just fine whenever I paste it into the script. But everytime I save the script and re-open it, the unicode characters become question marks and random gibberish characters. When "sendinput" is run, the output also comes out as question marks and gibberish, instead of the actual unicode emoticons.
MyVarEmoticon =
(Ltrim
What is your choice? (Enter #):
1. (╯°□°)╯︵ ┻━┻
2. (┛ಠ_ಠ)┛彡┻━┻
3. (╯°Д°)╯︵/(.□ . \)
4. ┏━┓┏━┓┏━┓ ︵ /(^.^/)
)
InputBox, MyVarEmoticonChoices, Emoticon Choices, %MyVarEmoticon%, , 400, % HEmoticon(MyVarEmoticon),,,,,1
HEmoticon(MyVarEmoticon)
{
StringReplace, MyVarEmoticon,myvaremoticon,`n,`n,UseErrorLevel
Lines:=ErrorLevel+1
height:=lines * 30 ; play with this value !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;MsgBox % height
If (Height < 40) ; too low
Height+=80
Return height
}
if ErrorLevel {
;MsgBox, CANCEL was pressed.
} else {
if (MyVarEmoticonChoices = "1"){
MyVarEmoticonChoices = (╯°□°)╯︵ ┻━┻
}
if (MyVarEmoticonChoices = "2"){
MyVarEmoticonChoices = (┛ಠ_ಠ)┛彡┻━┻
}
if (MyVarEmoticonChoices = "3"){
MyVarEmoticonChoices = (╯°Д°)╯︵/(.□ . \)
}
if (MyVarEmoticonChoices = "4"){
MyVarEmoticonChoices = ┏━┓┏━┓┏━┓ ︵ /(^.^/)
}
WinGetPos, X, Y, Width, Height, ahk_exe ToW.exe, , ,
XVar = %X%
YVar = %Y%
WVar = %Width%
HVar = %Height%
XWVar = % XVar+39
YHVar = % YVar+682
Sleep,200
sendinput, {raw}%MyVarEmoticonChoices%
Although there are some quite weird things in this code, it seems to work as expected if saved with the correct encoding.
I can't really know what goes wrong when you're trying to save it, maybe try to explain the steps you take to save it in the editor you're using.
If you don't want to worry about file encoding, you could store the characters as code points for example.
You can find a quick little converter with a Google search, here is the one I landed on with a Google search:
http://unicode.scarfboy.com/?s=%28%E2%95%AF%C2%B0%E2%96%A1%C2%B0%29%E2%95%AF%EF%B8%B5+%E2%94%BB%E2%94%81%E2%94%BB
And then you can convert to the code points to characters with Chr().
For example:
emote := "0028 256F 00B0 25A1 00B0 0029 256F FE35 0020 253B 2501 253B"
for each, codepoint in StrSplit(emote, " ")
output .= Chr("0x" codepoint)
Clipboard := output
SendInput, ^v
And here I'm also utilizing the clipboard and sending Ctrl+v, which is a good trick if you can use it. Especially for long text, which this really isn't I guess, but I figured I'd show it.
Or if you want to Send the string, you can use the Unicode notation:
emote := "0028 256F 00B0 25A1 00B0 0029 256F FE35 0020 253B 2501 253B"
for each, codepoint in StrSplit(emote, " ")
output .= "{U+" codepoint "}"
SendInput, % output
;SendInput, % "{U+0028}{U+256F}{U+00B0}{U+25A1}{U+00B0}{U+0029}{U+256F}{U+FE35}{U+0020}{U+253B}{U+2501}{U+253B}"
In ahk script files you must choose UTF-16 LE BOM Encoding to support Unicode characters. That's a Microsoft Windows default behaviour which indicates all other encodings as ASCII.

Manipulate UserDefined tag (TXXX frame) with Taglib-Sharp

Situation & Task
I have a large music collection and I want to clean their ID3V2 tags with PowerShell and taglip-sharp. Some tags like comment or encoding should be deleted while others like artist or title should not.
Usually you manipulate ID3 tags this way (Simplified version)
# Add taglib dll
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\taglib-sharp.dll")
# Load example mp3 into memory as [taglib.file]
$media = [TagLib.File]::Create("C:\path\to\musicFile.mp3")
# Change comment tag
$media.tag.tags[0].Comment = "Hello World"
# Save tags back to mp3 file
$Media.Save()
Problem
Many music files store custom information like URL or Shop Name in a frame called TXXX. Unfortunately, this frame is not accessible with the method shown above. Or I haven't found a way yet.
Instead you use
# Read UserTextInformationFrame
$media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX")
This User defined text information frame can hold multiple values. And some are useful since music players like Foobar store PERFORMER, DATE or replay_track_gain tags in TXXX.
Example output for the line above could be:
Description : replaygain_track_gain
Text : {-5.00 dB}
FieldList : {-5.00 dB}
TextEncoding : Latin1
FrameId : {84, 88, 88, 88}
Size : 32
Flags : None
GroupId : -1
EncryptionId : -1
Description : URL
Text : {www.amazon.com}
FieldList : {www.amazon.com}
TextEncoding : UTF16
FrameId : {84, 88, 88, 88}
Size : 43
Flags : None
GroupId : -1
EncryptionId : -1
After this, I was able to filter out all unnecessary TXXX values
# Create a whitelist of TXXX frames
$goodTXXX = 'performer','replaygain_track_gain','date'
# Read UserTextInformationFrame AND filter it
$newTXXX = $Media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX") |
where { $goodTXXX -contains $_.Description }
Question: How to write multiple values to TXXX frame
So my question is, how do I save my filtered results back to mp3 file?
My failed attempts were:
$media.GetTag([TagLib.TagTypes]::Id3v2).RemoveFrames("TXXX")
$media.GetTag([TagLib.TagTypes]::Id3v2).SetTextFrame("TXXX",$newTXXX)
# Removes old values, but does not show anything in Foobar
#$media.GetTag([TagLib.TagTypes]::Id3v2).GetFrames("TXXX").SetText("Hello World")
# Shows garbage in Foobar. And it's not usable for multiple values
Taglib-Sharp documentation for SetTextFrame
Bonus question: Is taglib-sharp able to strip out Id3v1 and ID3v2.4 tags while saving new tags as ID3v2.3 tags? (Related SO answer, but doesn't distinguish between v2.3 and v2.4)
I found a way with try & error. It's not elegant since you have to remove all TXXX values and add them back if you just want to change a single one
# Add taglib dll
[Void][System.Reflection.Assembly]::LoadFrom("$PSScriptRoot\taglib-sharp.dll")
# Load example mp3 into memory as [taglib.file]
$media = [TagLib.File]::Create("C:\path\to\musicFile.mp3")
# Get or create the ID3v2 tag.
[TagLib.Id3v2.Tag]$id3v2tag = $media.GetTag([TagLib.TagTypes]::Id3v2, 1)
# Create new 'TXXX frame' object
$TXXXFrame = [TagLib.Id3v2.UserTextInformationFrame]("WWW")
# Delete complete TXXX frame first, or else all values are just appended
$id3v2tag.RemoveFrames("TXXX")
# Set the value/text in the newly created TXXX frame, default Text encoding is UTF8
# Use curly brackets instead of single quotation marks
$TXXXFrame.Text = {www.myurl.com}
# Add TXXX frame to tag
$id3v2tag.AddFrame($TXXXFrame)
# Write all changed tags back to file
$media.Save()

Replace a middle string in .bat file using AutoHotKey without deleting file

I need to edit standalone.bat file using ahk script. I want to increase my heap size using ahk so below is line where i have to change heap in my bat file. Now i have trying to edit this using StringReplace and FileAppend but FileAppend keeps on appending string to the end
from
set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Xms64M -Xmx1426M %JAVA_OPTS%"
to
set "JAVA_OPTS=-Dprogram.name=%PROGNAME% -Xms64M -Xmx1426M %JAVA_OPTS%"xms000M
I am new to .ahk, i have tried this using some search
Loop, read, C:\standalone.bat
{
Line = %A_LoopReadLine%
replaceto = xms000M
IfInString, Line, Xmx1426M
, Line, replaceto, %Line%, %replaceto%
FileAppend, %replaceto%`n
StringReplace FileAppend
}
Is it possible to replace middle string using ahk. thanks
Fileappend will always append to the end of a file. Why do you want to prevent a temporary deletion of your batch file?
Typically, in ahk, you'd do it like this..
batFile = C:\standalone.bat
output := ""
Loop, read, %batFile%
{
Line = %A_LoopReadLine%
IfInString, Line, Xmx1426M
{
StringReplace, Line, Line, Xmx1426M, xms000M
; note: Regular Expressions can be used like Line := regExReplace(Line, "...", "...")
}
output .= Line . "`n" ; note: this is the same as if to say output = %output%%Line%`n or output := output . line "`n"
}
FileDelete, %batFile%
FileAppend, %output%, %batFile%
This will delete your file for some little milliseconds, just to recreate it with the new content afterwards. I don't really see any difference to editing it without deletion, because in either way, you'll need write access to the file.
Some words about your code sample:
IfInString, Line, Xmx1426M
, Line, replaceto, %Line%, %replaceto%
will be interpreted as
"If the string 'Line' contains 'Xmx1426M , Line, replaceto, %Line%, %replaceto%'"
which does not make any greater sense.
FileAppend, %replaceto%\n is lacking a destination file.
StringReplace FileAppend: these are two commands without any further parameters. You must never put two non-function-commands in the same line!

write a function in JES that will distinguish type of file is chosen

"Write a function that will obtain a file name (using pickAFile), and then recognise if it is a picture or a sound file, or even some other file type. The file should then be interpreted as either a picture, if its type is jpg (then print an appropriate message, then exit) or a sound, if its type is wav (then print an appropriate message, then exit), and if it is neither a picture nor a sound file, then an error message must be printed. This error message should include the type of the file (or the lack of a type, e.g. a file name that might not have a period in it, e.g. ducksjpg). Remember that file types can be 2, 3, 4 or even more letters long! "
So this is what I have figured out so far and it works:
def sortoutfiles():
f= pickAFile()
print f
filename=f
if filename.endswith (".jpg"):
print "It's a picture"
if filename.endswith (".wav"):
print " It's a sound"
else:
print"Oops! Did not choose a picture or a sound file"
For some reason the program doesnt work when I try to use rfind-get error message-invalid syntax on line 5
def sortoutfiles():
f= pickAFile()
print f
filename=f
if p=filename.rfind('.jpg'):
print "It's a picture"
if filename=f.rfind(".wav"):
print " It's a sound"
else:
print"Oops! Did not choose a picture or a sound file"
here
Can someone tell me what I am doing wrong in writing the program using rfind?
Apco 1P00?
Use rfind to figure out the file extension
f = pickAFile()
p = f.rfind('.jpg') #finds if the file ends in .jpg
s = f.rfind('.wav') #finds if the file ends in .wav
length = len(f) #finds the length of the file name
Use this as a foundation and go from here using if statements.
Recall the last lab.
>>> testString = 'abc DEf ghi ihg uVW xyz'
>>> print testString.find('k')
-1 #"Not found" can't be 0, so result is -1

Matlab Read Text File List Exclude first 34 characters

I am trying to read values from a text file. I want the value after ': '.
Here is a sample of the text file. All lines are formated the same.
There are 34 places before the start of the data.
File Name : IMG_1184.JPG
File Size : 2.1 MB
File Modification Date/Time : 2012:07:14 11:53:18-05:00
File Permissions : rw-rw-rw-
File Type : JPEG
MIME Type : image/jpeg
Exif Byte Order : Big-endian (Motorola, MM)
I tried to use this code:
fileID = fopen('Exif.txt');
Exif1 = textscan(fileID, '%s %s','delimiter', ':');
This worked on most of the data but some data also used ':' so that didn't work.
I tried to use this code:
fileID = fopen('Exif.txt');
Exif1 = textscan(fileID, '%s %s','delimiter', ': ');
This returned a mess. Not sure why. Everything was fragmented.
Can anyone explain how to just get the 35th value to the end of every string and put it into an array?
There is the function strtrim(string) in Matlab which will strip the leading and trailing spaces for you. Try reading the data in a line at the time into the textscan function after using strtrim?
Read the whole line into a variable then get the 35th and subsequent characters like this:
whole_line(35:end)