Preface:I'm a lazy worker
Our slogan is: can use the brain to solve the absolute do not rely on physical strength, can use the computer to complete the absolute do not rely on brain, can be lazy lazy, lazy miracle
1.1: About code
What do you see as code, the logic of a class? Method implementation? Don’t lose sight of an important essence: code is human-readable strings that can be compiled into executable files, so strings matter. I have written several articles about strings on and off, and the fundamental class of quantitative change often brings about the sublimation of qualitative change. Today I have a flash of inspiration, and this article. In order not to let the good ones go to waste, a few links written before are listed below:
1. Play string – code automatic generation, free hands 2. Play string – data everywhere is to see you take 3. MySQL has no material for strings String manipulation link 4. Playing with strings – The uncanny craftsmanship of substitution
1.2: The beginning of this article
Write Flutter custom components today, I want to create a StatefulWidget and put it in Gradle. I want to create a StatefulWidget and put it in Gradle. I want to create a StatefulWidget and put it in Gradle. This article focuses on the idea of strings
2. Template replacement parser:TemplateParser
This is the product of perfection on the basis of the uncanny workmanship of substitution
2). Optimized structure, replacing HashMap with Properties, and using configuration files 3). Support single file and folder multiple file replacementCopy the code
2.1: the use of the Properties
And before we do that, Properties (String to String mappings) Properties (String to String mappings) (String to String mappings Here create a config.properties on the outside of the project with the key value pair className=TolyWidget
public class Generation { public static void main(String[] args) throws IOException { Properties prop = new Properties(); // Read the properties file a.perties InputStreamin = new BufferedInputStream(new FileInputStream("config.properties"));
prop.load(in); Iterator<String> it = prop.stringPropertyNames().iterator();while (it.hasNext()) {
String key = it.next();
System.out.println(key + ":"+ prop.getProperty(key)); } in.close(); }} ---->[console output]---- className:TolyWidgetCopy the code
This allows you to use key-value pairs of strings in your code according to the configuration file
2.2: parsing classes
The end effect is to replace all corresponding identified parts of a template with the mapping string of the configuration file. The default configuration file location is at the root of the project, named config.properties, and output to the dest directory of the parent directory of the template
package generation; import java.io.*; import java.util.Iterator; import java.util.Map; import java.util.Properties; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; Public class TemplateParser {/** * default :$[X], custom note \\ escape */ private String symbol; private Properties properties; publicTemplateParser() {
this("\\$\\[X\\]"."config.properties"); } public TemplateParser(String symbol, String propFilePath) { this.symbol = symbol; loadProperties(propFilePath); } /** * Load configuration file * @param path Configuration file path */ private void loadProperties(String path) {properties = new properties (); // Read the properties file a.perties InputStreamin = null;
try {
in = new BufferedInputStream(new FileInputStream(path));
properties.load(in);
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in! = null) { in.close(); } } catch (IOException e) { e.printStackTrace(); }}} /** * Parse string ** @param target Target string * @returnPublic String Parser (String target) {String[] symbols = symbol.split("X");
Map<Integer, String> cutPos = new TreeMap<>();
String regex = symbols[0] + "(?
.*?) "
+ symbols[1];
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(target);
while (matcher.find()) {
String matchStr = matcher.group("result");
cutPos.put(matcher.end(), matchStr);
}
Iterator<Map.Entry<Integer, String>> iterator = cutPos.entrySet().iterator();
String temp;
int offset = 0;
while (iterator.hasNext()) {
Map.Entry<Integer, String> e = iterator.next();
int k = e.getKey();
String v = e.getValue();
String src = "$[" + v + "]";
String result = properties.getProperty(v);
String substring = target.substring(0, k + offset);
temp = substring.replace(src, result);
target = target.replace(substring, temp);
offset += result.length() - src.length();
}
returntarget; @param path Path */ public void parserDir(String path) {copyDir(path, path +"-dest"); // copy parserDir(new File(path +)"-dest"));
}
private void parserDir(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null) {
return;
}
for (File f : files) {
if (f.isDirectory()) {
parserDir(f);
} else{ saveFile(f, parserFile(file)); }}}else{ parserFile(file); }} /** * Parse a file ** @param path Path * @returnPublic String parserFile(String path) {File File = new File(path); String result = parserFile(new File(path)); String out = file.getParentFile().getParentFile().getAbsolutePath() + File.separator +"dest" + File.separator + file.getName();
saveFile(new File(out), result);
returnresult; } /** * param file * @param file * @returnPrivate String parserFile(File File) {InputStream is = null; StringBuilder sb = new StringBuilder(); try { is = new FileInputStream(file); int len = 0; byte[] buffer = new byte[1024];while((len = is.read(buffer)) ! = -1) { sb.append(new String(buffer, 0, len)); } } catch (Exception e) { e.printStackTrace(); } finally { try {if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
returnparser(sb.toString()); } / / = = = = = = = = = = = = = = = = = = = = = = = = = = files related to operating the = = = = = = = = = = = = = = = = = = = = = = = = = = = / save string file * * * * * @ param file file * @ param content string content */ private void saveFile(File file, String content) {ifNotExistMakeIt(file); FileWriter fw = null; try { fw = new FileWriter(file); // Write to disk fw.write(content); } catch (IOException e) { e.printStackTrace(); } finally { try {if(fw ! = null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); Private static void ** @param file */ private static void ** @param file */ private static voidifNotExistMakeIt(File file) {
if(file.exists()) {//2. Checks whether a file existsreturn; } File parent = file.getParentFile(); //3. Obtain the parent fileif(! parent.exists()) {if(! Parent-mkdirs ()) {//4. Create a parent filereturn; } } try { file.createNewFile(); } catch (IOException e) {e.printStackTrace(); } } private static voidifNotExistMakeIt(String path) { File file = new File(path); 1. Create a fileifNotExistMakeIt(file); } /** * copy the contents of the entire folder ** @param oldPath String Original file path * @param newPath String copied path * @returnboolean */ private void copyDir(String oldPath, String newPath) { try { (new File(newPath)).mkdirs(); // If the folder does not exist, create a new folder File a = new File(oldPath); String[] file = a.list(); File temp = null;if (file == null) {
return;
}
for (int i = 0; i < file.length; i++) {
if (oldPath.endsWith(File.separator)) {
temp = new File(oldPath + file[i]);
} else {
temp = new File(oldPath + File.separator + file[i]);
}
if (temp.isFile()) {
FileInputStream input = new FileInputStream(temp);
FileOutputStream output = new FileOutputStream(newPath + "/" +
(temp.getName()).toString());
byte[] b = new byte[1024 * 5];
int len;
while((len = input.read(b)) ! = -1) { output.write(b, 0, len); } output.flush(); output.close(); input.close(); }if(temp.isdirectory ()) {// If it is a subfolder copyDir(oldPath +"/" + file[i], newPath + "/" + file[i]);
}
}
} catch (Exception e) {
System.out.println("Replication error"); e.printStackTrace(); }}}Copy the code
There are a lot of common file operations, you can also pick out a tool class collection
3. How to use Java code in Gradle
Gradle- Gradle- Gradle- Gradle
3.1: Task and path fetching in Gradle
Create a new task. On the left, Gradle->other will have the corresponding task. Click on it to run the code
---->[app/build.gradle back]---- taskgenerationTask() {// Define a taskdoFirst {
String root=System.getProperty("user.dir");
println("hello gradel:"+root)
}
Copy the code
3.2: Reading configuration files in Gradle
Gradle uses the Java-compatible Groovy language, so Java code can also run. Create the Generation folder under the project root file to hold configuration files, templates and output files
task generationTask() {// Define a taskdoFirst {
String root=System.getProperty("user.dir");
println("hello gradel:"+root) Properties prop = new Properties(); A.properties InputStream is = new BufferedInputStream(new FileInputStream(root+)"/generation/config.properties")); prop.load(is); Iterator<String> itor = prop.stringPropertyNames().iterator();while (itor.hasNext()) {
String key = itor.next();
System.out.println(key + ":"+ prop.getProperty(key)); } is.close(); }}Copy the code
Then run to see the result :className:TolyWidget
3.3:
Copy all the classes I just wrote down here. Let’s talk about a couple of bad points
${$} = ${$} = ${$}; Functions can't be overloaded, for fuck's sakeCopy the code
3.4: Plug-in and split file import
The plugin logic is extracted into another file and put in the generation package. In this way, everything needed for the whole process is kept together. We only need to worry about the template and configuration. With a single click, everything that needs to be replaced in the template is done
---->[下 载,app/build.gradle]---- apply from:"./generation/generation.gradle"
Copy the code
3.5: generation. Gradle overview
Just copy this and use it. In the future, if there is anything that is annoying and has no technical content, change it in batches.
// Create By Tolyin2019.7.17 -- -- -- -- -- -- -- -- -- the apply the plugin: TemplateParserPlugin / / statement using plug-in / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the following is a plug-in part -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the class TemplateParserPlugin Plugin<Project> {// This interface defines a method called apply(), in which we can manipulate projects, such as adding tasks to them, Define additional properties, etc. Void the apply (Project Project) {/ / load the Extension Project. The extensions. Create ("Config"// Use the Extension configuration information project.task('TemplateParser') << {
String path = project.Config.root
new TemplateParser(path+"config.properties")
.parserFile(path+"template/StatefulTemplate.txt"String root = system.getProperty (String root = system.getProperty ("user.dir") +"/generation/"} / / / -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the following is a class -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- the import Java. Util. Regex. Matcher. import java.util.regex.Pattern; Public class TemplateParser {/** * default :$[X], custom note \\ escape */ private String symbol; private Properties properties; publicTemplateParser() {
this('\\$\\[X\\]'."config.properties");
}
public TemplateParser( String propFilePath) {
this('\\$\\[X\\]',propFilePath); } public TemplateParser(String symbol, String propFilePath) { this.symbol = symbol; loadProperties(propFilePath); } /** * Load configuration file * @param path Configuration file path */ private void loadProperties(String path) {properties = new properties (); A.properties InputStream is = null; try { is = new BufferedInputStream(new FileInputStream(path)); properties.load(is); } catch (IOException e) { e.printStackTrace(); } finally { try {if(is ! = null) { is.close(); } } catch (IOException e) { e.printStackTrace(); }}} /** * Parse string ** @param target Target string * @returnPublic String Parser (String target) {String[] symbols = symbol.split("X");
Map<Integer, String> cutPos = new TreeMap<>();
String regex = symbols[0] + ". *?" + symbols[1];
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(target);
while (matcher.find()) {
String matchStr = matcher.group(0);
String v = matchStr.split(symbols[0])[1].split(symbols[1])[0]
cutPos.put(matcher.end(), v);
}
Iterator<Map.Entry<Integer, String>> iterator = cutPos.entrySet().iterator();
String temp;
int offset = 0;
while (iterator.hasNext()) {
Map.Entry<Integer, String> e = iterator.next();
int k = e.getKey();
String v = e.getValue();
String src = '$[' + v + "]";
String result = properties.getProperty(v);
String substring = target.substring(0, k + offset);
temp = substring.replace(src, result);
target = target.replace(substring, temp);
offset += result.length() - src.length();
}
returntarget; @param path Path */ public void parserDir(String path) {copyDir(path, path +"-dest"); _parserDir(new File(path +)"-dest"));
}
private void _parserDir(File file) {
if (file.isDirectory()) {
File[] files = file.listFiles();
if (files == null) {
return;
}
for (File f : files) {
if (f.isDirectory()) {
parserDir(f);
} else{ saveFile(f, parserFile(file)); }}}else{ parserFile(file); }} /** * Parse a file ** @param path Path * @returnPublic String parserFile(String path) {File File = new File(path); String result = _parserFile(new File(path)); String out = file.getParentFile().getParentFile().getAbsolutePath() + File.separator +"dest" + File.separator + file.getName();
saveFile(new File(out), result);
returnresult; } /** * param file * @param file * @returnParsed String */ private String _parserFile(File File) {InputStream is = null; StringBuilder sb = new StringBuilder(); try { is = new FileInputStream(file); int len = 0; byte[] buffer = new byte[1024];while((len = is.read(buffer)) ! = -1) { sb.append(new String(buffer, 0, len)); } } catch (Exception e) { e.printStackTrace(); } finally { try {if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
returnparser(sb.toString()); } / / = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = files related to operating the = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = / * * * * * to save the string file @param file file * @param Content String content */ private void saveFile(file file, String content) {ifNotExistMakeIt(file); FileWriter fw = null; try { fw = new FileWriter(file); // Write to disk fw.write(content); } catch (IOException e) { e.printStackTrace(); } finally { try {if(fw ! = null) { fw.close(); } } catch (IOException e) { e.printStackTrace(); Private static void ** @param file */ private static void ** @param file */ private static voidifNotExistMakeIt(File file) {
if(file.exists()) {//2. Checks whether a file existsreturn; } File parent = file.getParentFile(); //3. Obtain the parent fileif(! parent.exists()) {if(! Parent-mkdirs ()) {//4. Create a parent filereturn; } } try { file.createNewFile(); } catch (IOException e) {e.printStackTrace(); } } private static voidifNotExistMakeIt(String path) { File file = new File(path); 1. Create a fileifNotExistMakeIt(file); } /** * copy the contents of the entire folder ** @param oldPath String Original file path * @param newPath String copied path * @returnboolean */ private void copyDir(String oldPath, String newPath) { try { (new File(newPath)).mkdirs(); // If the folder does not exist, create a new folder File a = new File(oldPath); String[] file = a.list(); File temp = null;if (file == null) {
return;
}
for (int i = 0; i < file.length; i++) {
if (oldPath.endsWith(File.separator)) {
temp = new File(oldPath + file[i]);
} else {
temp = new File(oldPath + File.separator + file[i]);
}
if (temp.isFile()) {
FileInputStream input = new FileInputStream(temp);
FileOutputStream output = new FileOutputStream(newPath + "/" +
(temp.getName()).toString());
byte[] b = new byte[1024 * 5];
int len;
while((len = input.read(b)) ! = -1) { output.write(b, 0, len); } output.flush(); output.close(); input.close(); }if(temp.isdirectory ()) {// If it is a subfolder copyDir(oldPath +"/" + file[i], newPath + "/" + file[i]);
}
}
} catch (Exception e) {
System.out.println("Error copying entire folder contents"); e.printStackTrace(); }}}Copy the code