//
// https://www.ramecera.it/myscrewdriver.html
// e-mail: screwdriver@ramecera.it
//
/* This program and the accompanying materials are made available under
 * the terms of the Eclipse Public License v1.0 which accompanies this
 * distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html */
package it.ramecera.salad.file;

import java.io.BufferedInputStream;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.log4j.Logger;

import it.ramecera.salad.everyday.Candies;
import it.ramecera.salad.everyday.ExactException;
import it.ramecera.salad.everyday.Mix;
import it.ramecera.salad.graphic.Placard;

/**
 * <p>
 * Class for reading files. The class should not be instantiated.
 * </p>
 * <p>
 * Company: Ramecera™<br>
 * Creation date: 2020-04-09<br>
 * Last updated: 2020-04-09
 * </p>
 * <p>
 * Changes:<br>
 * 2020-04-09: various methods added 2020-04-09: modification of
 * unicaStringaUnicode_B and creation of entities_A<br>
 * </p>
 * 
 * @author M. Maglioni */

public class Equipment {

	/** char Line Feed */
	public final static char LF = 10; // the line feed character
	/** Line Feed font */
	public final static String LFS = Character.valueOf(LF).toString();

	/**
	 * <p>
	 * Reading a sequential file to deposit it on a single string. The
	 * file is fully deposited, for example the CR and/or LF are
	 * inserted exactly like all the other characters.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file input file
	 * @return string with the entire contents of the
	 * @throws FileNotFoundException is triggered when the file does not
	 *         exist
	 * @throws IOException is triggered when it cannot be read, for any
	 *         other reason. */
	public static String oneString(File file)

			throws IOException, FileNotFoundException {

		String s;
		int j, k;
		BufferedInputStream bis = null;
		try {
			FileInputStream fis = new FileInputStream(file);
			bis = new BufferedInputStream(fis);
			j = (int) file.length();
			char[] c = new char[j];
			for (k = 0; k < j; k++)
				c[k] = (char) bis.read();
			bis.close();
			s = new String(c);
		} catch (FileNotFoundException e) {
			throw e;
		} catch (IOException e) {
			bis.close();
			throw e;
		}
		return s;
	}

	/**
	 * <p>
	 * Overload of the previous method.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param g file name, including all path
	 * @return the all-inclusive string of all text
	 * @throws IOException ordinary exception
	 * @throws FileNotFoundException ordinary exception
	 * @since 1.0.0 - SVutensiliJ4_1.3.0 */
	public static String oneString(final String g)

			throws IOException, FileNotFoundException {

		return oneString(new File(g));
	}

	/**
	 * <p>
	 * Overload of the previous method.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param is the InputStream object to read
	 * @return the all-inclusive string of all text
	 * @throws IOException ordinary exception
	 * @throws FileNotFoundException ordinary exception
	 * @since 3 */
	public static String unicaStringa(InputStream is)

			throws IOException, FileNotFoundException {

		String s;
		int j, k;
		BufferedInputStream bis = null;
		try {
			bis = new BufferedInputStream(is);
			j = is.available();
			char[] c = new char[j];
			for (k = 0; k < j; k++)
				c[k] = (char) bis.read();
			bis.close();
			s = new String(c);
		} catch (FileNotFoundException e) {
			throw e;
		} catch (IOException e) {
			bis.close();
			throw e;
		}
		return s;
	}

	/**
	 * <p>
	 * Reading of a sequential file to deposit it on a single string,
	 * with transformation in UTF. The file is fully deposited, for
	 * example the CR and/or LF are inserted exactly like all the other
	 * characters.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file input file
	 * @param code code to be adopted
	 * @return string with the entire contents of the file
	 * @throws ExactException standard exception */
	public static String oneStringUnicode_A(File file,
			final String code)

			throws ExactException {

		String s;
		InputStreamReader isr = null;
		if (file.length() > Integer.MAX_VALUE) {
			throw new ExactException(
					"The file length is greater than 2 GB,"
							+ " it is not allowed.", 1108, "Equipment",
					"oneStringUnicode_A");
		} else if (file.length() == 0) {
			return "";
		}
		try {
			FileInputStream fis = new FileInputStream(file);
			isr = new InputStreamReader(fis, code);
			int j = (int) file.length();
			char[] c = new char[j];
			isr.read(c);
			isr.close();
			int i;
			for (i = j - 1; c[i] == 0; i--)
				;
			s = (new String(c)).substring(0, i + 1);
		} catch (UnsupportedEncodingException uee) {
			throw new ExactException(uee.getMessage(), 100908,
					"Equipment", "oneStringUnicode_A");
		} catch (FileNotFoundException fnfe) {
			throw new ExactException("The file " + file.getPath()
					+ " was not found.", 100909, "Equipment",
					"oneStringUnicode_A");
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage(), 100910,
					"Equipment", "oneStringUnicode_A");
		} finally {
			try {
				isr.close();
			} catch (IOException e) {
				// do nothing
			}
		}
		return s;
	}

	/**
	 * <p>
	 * Reading of a sequential file to deposit it on a single string,
	 * with transformation in UTF. Overload of the previous one.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09<br>
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param f input file
	 * @param code code to be adopted
	 * @return string with the entire contents of the file
	 * @throws ExactException standard exception */
	public static String oneStringUnicode_A(final String f,
			final String code)

			throws ExactException {

		return oneStringUnicode_A(new File(f), code);
	}

	/**
	 * <p>
	 * Reading of a sequential file to deposit it on a single string,
	 * with transformation into UTF and use of XML-character
	 * &amp;#xffff;.<br>
	 * By <i> ffff </i> we mean 4 hexadecimal characters, example :
	 * e445, 00fe, ff4a, etc. which correspond to 16 bits.<br>
	 * The code is regulated by the production [66] of the W3C.<br>
	 * The file is fully deposited, for example the CR and / or LF are
	 * inserted exactly like all the other characters.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Modifications:<br>
	 * 29/12 08: extraction of part of the argorithm in the new
	 * entities_A method.<br>
	 * 2020-04-09: replacement of the entities_A method with entities_B,
	 * to avoid saturation of the heap<br>
	 * </p>
	 * 
	 * @param file input file
	 * @param code code to be adopted
	 * @return string with l the entire contents of the
	 * @throws FileNotFoundException is triggered when the file does not
	 *         exist
	 * @throws IOException is triggered when it is not possible to read,
	 *         for any other reason.
	 * @throws UnsupportedEncodingException UTF codes do not exist in
	 *         that combination
	 * @since 2.0.0 - SVutensiliJ4_1.3.0 */
	public static String unicaStringaUnicode_B(File file,
			final String code)

			throws UnsupportedEncodingException, IOException {

		String t = null;
		InputStreamReader isr = null;
		if (file.length() > Integer.MAX_VALUE / 2)
			throw new IOException(
					"The file length is greater than 1 GB, it is not allowed.");
		try {
			FileInputStream fis = new FileInputStream(file);
			isr = new InputStreamReader(fis, code);
			int m = (int) file.length();
			char[] c = new char[m]; // I prepare the array to
								    // accommodate i
								    // characters of the file
			isr.read(c); // load the array c
			isr.close(); // I close the file
			t = String.valueOf(c);
		} catch (FileNotFoundException e) {
			throw e;
		} catch (IOException e) {
			isr.close();
			throw e;
		}
		return entities_C(t);
	}

	/**
	 * <p>
	 * Overload of the previous method.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param is the InputStream object to be read
	 * @param code encoding UNICODE
	 * @return the all-inclusive string of all text
	 * @throws UnsupportedEncodingException ordinary exception
	 * @throws IOException ordinary exception
	 * @throws FileNotFoundException ordinary exception
	 * @since 3 */
	public static String unicaStringaUnicode_B(InputStream is,
			final String code)

			throws UnsupportedEncodingException, IOException {

		String t = null;
		InputStreamReader isr = null;
		if (is.available() > Integer.MAX_VALUE / 2)
			throw new IOException(
					"The file length is greater than 1 GB, it is not allowed.");
		try {
			isr = new InputStreamReader(is, code);
			int m = is.available();
			char[] c = new char[m]; // I prepare the array to
								    // accommodate i
								    // characters of the file
			isr.read(c); // load the array c
			isr.close(); // I close the file
			t = String.valueOf(c);
		} catch (IOException e) {
			isr.close();
			throw e;
		}
		return entities_C(t);
	}

	/**
	 * <p>
	 * String-to-string transformation, using XML-character
	 * &amp;#xffff;.<br>
	 * By <i> ffff </i> we mean 4 hexadecimal characters, for example:
	 * e445, 00fe, ff4a, etc. which correspond to 16 bits.<br>
	 * The code is regulated by W3C production [66].<br>
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 29 / 04/08
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param t input string
	 * @return oputput string */
	public static String entities_A(final String t) {
		if (t == null) {
			return null;
		}
		String s;
		int m = t.length();
		if (m == 0) {
			return t;
		}
		/* I prepare the array to accommodate the characters of the
		 * file */
		char[] c = new char[m];
		c = t.toCharArray(); // load the array c
		int k;
		/* downgraded to not process any null in the queue */
		for (k = m - 1; c[k] == 0; k--)
			;
		/* at this point we start looking for unicode characters; you
		 * have chosen to convert to &#xffff; all characters beyond 255
		 * of the ASCII. */
		/* I prepare another 8 times long array, because they could all
		 * be special characters */
		char[] d = new char[(k + 1) * 8];
		/* there are 2 parallel scrolling indices, i and j, but every
		 * now and then j jumps 7 more points because we have
		 * encountered the sequence &#xffff; */
		int i, j;
		for (i = 0, j = 0; i <= k; i++, j++) {
			if (c[i] < 256)
				d[j] = c[i];
			else {
				char[] uno = new char[1];
				char[] esa = new char[4];
				uno[0] = c[i];
				esa = Mix.fromCharToEsadUnicode(uno);
				d[j] = '&';
				d[j + 1] = '#';
				d[j + 2] = 'x';
				d[j + 3] = esa[0];
				d[j + 4] = esa[1];
				d[j + 5] = esa[2];
				d[j + 6] = esa[3];
				d[j + 7] = ';';
				j += 7;
			}
		}
		String r = new String(d);
		s = r.substring(0, j);
		return s;
	}

	/**
	 * <p>
	 * Variant of the previous one, it only makes the amount of heap
	 * memory required by the JVM variable. This variant was introduced
	 * because the multiplier 8 in the new char of the original version
	 * of the method was excessive when applying the method to an entire
	 * file, corrected when applying to a simple sentence, as happens in
	 * the justify_A method of the class it.ipzs.utensiliJN
	 * .comuni.Giustificazione. The multiplier becomes a topic of the
	 * method.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param t input string
	 * @param h multiplier to decide how much heap memory space to take
	 * @return oputput string
	 * @since 3.0.0 - SVutensiliJ4_2.0.0 */
	public static String entities_A(final String t, final int h) {
		if (t == null) {
			return null;
		}
		String s;
		int m = t.length();
		if (m == 0) {
			return t;
		}
		char[] c = new char[m]; // I prepare the array to accommodate i
							    // characters
							    // of the file
		c = t.toCharArray(); // load the array c
		int k;
		for (k = m - 1; c[k] == 0; k--)
			; // downgraded to not process any null in the queue
		/* at this point we start looking for unicode characters; you
		 * have chosen to convert to &#xffff; all characters beyond 255
		 * of the ASCII. */
		// I prepare another array long h times, because they could
		// to be
		// all
		// Special characters
		char[] d = new char[(k + 1) * h];
		/* there are 2 parallel scrolling indices, i and j, but every
		 * now and then j jumps 7 more points because we have
		 * encountered the sequence &#xffff; */
		int i, j;
		for (i = 0, j = 0; i <= k; i++, j++) {
			if (c[i] < 256)
				d[j] = c[i];
			else {
				char[] uno = new char[1];
				char[] esa = new char[4];
				uno[0] = c[i];
				esa = Mix.fromCharToEsadUnicode(uno);
				d[j] = '&';
				d[j + 1] = '#';
				d[j + 2] = 'x';
				d[j + 3] = esa[0];
				d[j + 4] = esa[1];
				d[j + 5] = esa[2];
				d[j + 6] = esa[3];
				d[j + 7] = ';';
				j += 7;
			}
		}
		String r = new String(d);
		s = r.substring(0, j);
		return s;
	}

	/**
	 * <p>
	 * String-to-string transformation, using XML-character
	 * &amp;#xffff;.<br>
	 * By <i> ffff </i> we mean 4 hexadecimal characters, for example:
	 * e445, 00fe, ff4a, etc. . which correspond to 16 bits.<br>
	 * The code is regulated by W3C production [66].<br>
	 * Version perfected compared to entities_A.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param t input string
	 * @return oputput string
	 * @since 3.0.0 - SVutensiliJ4_2.0.0 */
	public static String entities_C(final String t) {
		return entities_C(t, 255);
	}

	/**
	 * <p>
	 * String-to-string transformation, using XML-character
	 * &amp;#xffff;.<br>
	 * By <i> ffff </i> we mean 4 hexadecimal characters, for example:
	 * e445, 00fe, ff4a, etc. . which correspond to 16 bits.<br>
	 * The code is regulated by W3C production [66].<br>
	 * Version perfected compared to entities_A.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param t input string
	 * @param limit limit beyond which the input transformation is
	 *        triggered
	 * @return oputput string
	 * @since 3.0.0 - SVutensiliJ4_2.0.0 */
	public static String entities_C(final String t, final int limit) {
		if (t == null) {
			return null;
		}
		String s;
		int m = t.length();
		if (m == 0) {
			return t;
		}
		char[] c = new char[m]; // I prepare the array to accommodate i
							    // characters
							    // of the file
		c = t.toCharArray(); // load the array c
		int k;
		for (k = m - 1; c[k] == 0; k--)
			; // downgraded to not process any null in the queue
		int i, j, n;
		n = 0;
		for (i = 0; i <= k; i++) { // count in n how many characters
								   // will
								   // to be transformed
			if (c[i] > limit)
				n++;
		}
		/* at this point we start looking for unicode characters; you
		 * have chosen to convert to &#xffff; all characters beyond 255
		 * of the ASCII. */
		/* I prepare another quite long array, taking into account the
		 * count of the characters just made */
		char[] d = new char[k + 1 + n * 7];
		/* there are 2 parallel scrolling indices, i and j, but every
		 * now and then j jumps 7 more points because we have
		 * encountered the sequence &#xffff; */
		for (i = 0, j = 0; i <= k; i++, j++) {
			if (c[i] > limit) {
				char[] uno = new char[1];
				char[] esa = new char[4];
				uno[0] = c[i];
				esa = Mix.fromCharToEsadUnicode(uno);
				d[j] = '&';
				d[j + 1] = '#';
				d[j + 2] = 'x';
				d[j + 3] = esa[0];
				d[j + 4] = esa[1];
				d[j + 5] = esa[2];
				d[j + 6] = esa[3];
				d[j + 7] = ';';
				j += 7;
			} else {
				d[j] = c[i];
			}
		}
		String r = new String(d);
		s = r.substring(0, j);
		return s;
	}

	/**
	 * <p>
	 * Transformation of a text containing <i> hexadecimal character
	 * reference </i> into an ordinary 16-bit string per character; the
	 * code is regulated by W3C production [66].
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param s string to be written
	 * @return the Unicode string
	 * @since SVutensiliJ4_1.3.0 */
	public static String entities_Z(final String s) {

		int k = 0, m = 0;
		char[] h = new char[4]; // the 4 hexadecimal characters; es.
							    // 45ea,
							    // 005b,
							    // etc.
		int sL = s.length();
		char[] c = s.toCharArray(); // the array of input characters
		char[] d = new char[sL]; // the array of characters in output
		char[] uno = new char[1]; // the unicode character obtained
		try {
			/* I'm looking for the combination &#x (& = 38, # = 35, x =
			 * 120), and a semicolon (; = 59) further ahead */
			for (k = 0, m = 0; k < sL; k++, m++) {
				if (k < sL - 7 && c[k] == 38 && c[k + 1] == 35 && c[k
						+ 2] == 120 && c[k + 7] == 59) {
					h[0] = c[k + 3];
					h[1] = c[k + 4];
					h[2] = c[k + 5];
					h[3] = c[k + 6];
					uno = Mix.daEsadACharUnicode(h);
					d[m] = uno[0];
					k += 7;
				} else {
					d[m] = c[k];
				}
			}
		} catch (ExactException e) {
			System.out.println(
					"Uncorrect Hexadecimal codes were found: " + String
							.copyValueOf(h));
		}
		return new String(d);
	}

	/**
	 * <p>
	 * Writing a sequential file starting from the text of a string.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file output file
	 * @param s string to write
	 * @throws ExactException is triggered when the directory does not
	 *         exist, or the file cannot be written */
	public static void scriviFileDaStringa(File file, final String s)

			throws ExactException {

		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(
					new FileWriter(file)));
			out.print(s);
			out.close();
		} catch (FileNotFoundException nfe) {
			throw new ExactException(nfe.getMessage()
					+ " - Not found directory: " + file.getName() + ".",
					100900, "Equipment", "");
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage()
					+ " - It is impossible to write in " + file
							.getName() + ".", 100901, "Equipment", "");
		}
	}

	/**
	 * <p>
	 * Writing a sequential file starting from the text of a string. It
	 * differs from the writeFileFromStringa method because if
	 * everything is already exactly written it does nothing.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file input file
	 * @param s string to write false
	 * @return if the file was not written, for economy, being already
	 *         present and identical; true if
	 * @throws ExactException is triggered when the directory does not
	 *         exist, or it is not possible to write to the file */
	public static boolean writeFileFromOneString_economy(File file,
			final String s)

			throws ExactException {

		try {
			String t = oneString(file);
			// if everything is already exactly written, go away
			if (t.equals(s))
				return false;
		} catch (FileNotFoundException e) {
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(
					new FileWriter(file)));
			out.print(s);
			out.close();
		} catch (FileNotFoundException nfe) {
			throw new ExactException(nfe.getMessage()
					+ " - Not found directory «" + file.getName()
					+ "».", 100902, "Equipment", "");
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage()
					+ " - It is impossible to write in the file «"
					+ file.getName() + "»", 100903, "Equipment", "");
		}
		return true;
	}

	/**
	 * <p>
	 * Writing a sequential file starting from the text of a string,
	 * with transformation in UTF.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file output file
	 * @param s string to be written
	 * @param code Unicode code to be adopted
	 * @throws ExactException is triggered when the directory does not
	 *         exist, or it is not possible to write to the file */
	public static void writeFileFromOneStringUnicode_A(File file,
			final String s, final String code)

			throws ExactException {

		try {
			FileOutputStream fos = new FileOutputStream(file);
			OutputStreamWriter osw = new OutputStreamWriter(fos, code);
			osw.write(s, 0, s.length());
			osw.close();
		} catch (FileNotFoundException nfe) {
			throw new ExactException(nfe.getMessage()
					+ ", or not found the directory «" + file.getName()
					+ "».", 100904, "Equipment", "");
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage()
					+ " - It is impossible to write in the «" + file
							.getName() + "».", 100905, "Equipment", "");
		}
	}

	/**
	 * <p>
	 * Writing a sequential file starting from the text of a string,
	 * with transformation in UTF-16 and use of XML character-entity
	 * &amp;#xffff;.<br>
	 * The code is regulated by W3C production [66].
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file output file
	 * @param s string to be written
	 * @param code Unicode code to be adopted
	 * @throws ExactException is triggered when the directory does not
	 *         exist, or it is not possible to write to the file */
	public static void scriviFileDaStringaUnicode_B(File file,
			final String s, final String code)

			throws ExactException {

		int k = 0, m = 0;
		char[] h = new char[4]; // the 4 hexadecimal characters; es.
							    // 45ea,
							    // 005b,
							    // etc.
		int sL = s.length();
		char[] c = s.toCharArray(); // the array of input characters
		char[] d = new char[sL]; // the array of characters in output
		char[] uno = new char[1]; // the unicode character obtained
		try {
			/* I'm looking for the combination &#x (& = 38, # = 35, x =
			 * 120), and a semicolon (; = 59) further ahead */
			for (k = 0, m = 0; k < sL; k++, m++) {
				if (k < sL - 7 && c[k] == 38 && c[k + 1] == 35 && c[k
						+ 2] == 120 && c[k + 7] == 59) {
					h[0] = c[k + 3];
					h[1] = c[k + 4];
					h[2] = c[k + 5];
					h[3] = c[k + 6];
					uno = Mix.daEsadACharUnicode(h);
					d[m] = uno[0];
					k += 7;
				} else {
					d[m] = c[k];
				}
			}
		} catch (ExactException e) {
			System.out.println("Trovati codici esadecimali scorretti: "
					+ String.copyValueOf(h));
		}
		String r = new String(d);
		// if (replacement)
		// m--; // when the character entity is in last place,
		// must
		// a correction
		try {
			FileOutputStream fos = new FileOutputStream(file);
			OutputStreamWriter osw = new OutputStreamWriter(fos, code);
			osw.write(r, 0, m);
			osw.close();
		} catch (FileNotFoundException nfe) {
			throw new ExactException(nfe.getMessage()
					+ " - Not found the directory «" + file.getName()
					+ "».", 100906, "Equipment", "");
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage()
					+ " - It is impossible to write in the file «"
					+ file.getName() + "».", 100907, "Equipment", "");
		}
	}

	/**
	 * <p>
	 * Writing a file extracted from a zip, assuming the presence of
	 * Unicode characters.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param z the zip file
	 * @param ze entry (i.e. internal element) of the zip file
	 * @param output output file
	 * @param code the type of encoding Unicode
	 * @throws ExactException is triggered when the directory does not
	 *         exist, or it is not possible to write to the file
	 * @throws IOException standard exception
	 * @since 3 */
	public static void scriviZipEntry(ZipFile z, ZipEntry ze,
			File output, final String code)

			throws ExactException, IOException {

		InputStream is = z.getInputStream(ze);
		String unica = Equipment.unicaStringaUnicode_B(is, code);
		unica = "<?xml version=\"1.0\" encoding=\"" + code + "\"?>"
				+ LFS + unica;
		Equipment.scriviFileDaStringaUnicode_B(output, unica, code);
	}

	/**
	 * <p>
	 * Writing an empty file; if it already exists, empty or full, the
	 * method does nothing; if èd is a directory, the method does
	 * nothing.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param file the file to be created
	 * @throws ExactException is triggered when the file cannot be
	 *         written, for example because the path is wrong. */
	public static void scriviFileVuoto(File file)

			throws ExactException {

		if (file.exists()) {
			return;
		}
		try {
			PrintWriter out = new PrintWriter(new BufferedWriter(
					new FileWriter(file)));
			out.close();
		} catch (IOException ioe) {
			throw new ExactException(ioe.getMessage()
					+ " - It is impossible to write in the file " + file
							.getName() + ".", 100908, "Equipment", "");
		}
	}

	/**
	 * <p>
	 * Overload of the previous one.
	 * </p>
	 * <p>
	 * Creation date: 2020-04-09<br>
	 * Last updated: 2020-04-09
	 * </p>
	 * <p>
	 * Changes:<br>
	 * </p>
	 * 
	 * @param s the file to be created
	 * @throws ExactException is triggered when the file cannot be
	 *         written, for example because the path is wrong. */
	public static void scriviFileVuoto(final String s)

			throws ExactException {

		scriviFileVuoto(new File(s));
	}

	/**
	 * <p>
	 * Creation date: 2020-10-06<br>
	 * Class: Sweat
	 * </p>
	 * <p>
	 * Description: this method read a file, modify one time the
	 * corresponding string, finally write it.
	 * </p>
	 * 
	 * @param dY directory
	 * @param f name of the file to be modified
	 * @param x regular expression
	 * @param y replacement */
	static public boolean surgery(final String dY, final String f,
			final String x, final String y, Logger logger) {

		File file = new File(Mix.dress_C(dY) + f);
		if (!file.exists() || !file.isFile()) {
			Mix.discloseError("The file " + Mix.dress_A(f)
					+ " is not present. It is not possible to continue.",
					"Stop", logger);
			return false;
		}
		try {
			/* I am reading inside drill */
			String p0 = Equipment.oneStringUnicode_A(file, "UTF-8");
			/* I am updating */
			String p1 = p0.replaceFirst(x, y);
			/* I am writing inside drill */
			FileOutputStream fos = new FileOutputStream(file);
			OutputStreamWriter osw;
			osw = new OutputStreamWriter(fos, "UTF-8");
			osw.write(p1, 0, p1.length());
			osw.close();
		} catch (ExactException e) {
			String message = "";
			if (e.className != null) {
				message += "Class: " + e.className + Candies.LF;
			}
			if (e.method != null) {
				message += "Method: " + e.method + Candies.LF;
			}
			if (e.datum != null) {
				message += Candies.LF + e.datum;
			}
			logger.error(message);
			new Placard(null, message, "Error code " + e.code);
			return false;
		} catch (IOException e) {
			Mix.discloseError("I/O error on The file " + Mix.dress_A(
					file.getAbsolutePath())
					+ ". It is not possible to continue." + Candies.LF
					+ e.getMessage(), "Stop", logger);
			return false;
		}
		return true;
	}
}